aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_conexant.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/hda/patch_conexant.c')
-rw-r--r--sound/pci/hda/patch_conexant.c1835
1 files changed, 1492 insertions, 343 deletions
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 972e7c453b3d..7bbc5f237a5e 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -39,6 +39,7 @@
39 39
40#define CONEXANT_HP_EVENT 0x37 40#define CONEXANT_HP_EVENT 0x37
41#define CONEXANT_MIC_EVENT 0x38 41#define CONEXANT_MIC_EVENT 0x38
42#define CONEXANT_LINE_EVENT 0x39
42 43
43/* Conexant 5051 specific */ 44/* Conexant 5051 specific */
44 45
@@ -49,17 +50,22 @@
49#define AUTO_MIC_PORTB (1 << 1) 50#define AUTO_MIC_PORTB (1 << 1)
50#define AUTO_MIC_PORTC (1 << 2) 51#define AUTO_MIC_PORTC (1 << 2)
51 52
52struct conexant_jack { 53struct pin_dac_pair {
53 54 hda_nid_t pin;
54 hda_nid_t nid; 55 hda_nid_t dac;
55 int type; 56 int type;
56 struct snd_jack *jack; 57};
57 58
59struct imux_info {
60 hda_nid_t pin; /* input pin NID */
61 hda_nid_t adc; /* connected ADC NID */
62 hda_nid_t boost; /* optional boost volume NID */
63 int index; /* corresponding to autocfg.input */
58}; 64};
59 65
60struct conexant_spec { 66struct conexant_spec {
61 67
62 struct snd_kcontrol_new *mixers[5]; 68 const struct snd_kcontrol_new *mixers[5];
63 int num_mixers; 69 int num_mixers;
64 hda_nid_t vmaster_nid; 70 hda_nid_t vmaster_nid;
65 71
@@ -76,12 +82,17 @@ struct conexant_spec {
76 */ 82 */
77 unsigned int cur_eapd; 83 unsigned int cur_eapd;
78 unsigned int hp_present; 84 unsigned int hp_present;
85 unsigned int line_present;
79 unsigned int auto_mic; 86 unsigned int auto_mic;
87 int auto_mic_ext; /* imux_pins[] index for ext mic */
88 int auto_mic_dock; /* imux_pins[] index for dock mic */
89 int auto_mic_int; /* imux_pins[] index for int mic */
80 unsigned int need_dac_fix; 90 unsigned int need_dac_fix;
91 hda_nid_t slave_dig_outs[2];
81 92
82 /* capture */ 93 /* capture */
83 unsigned int num_adc_nids; 94 unsigned int num_adc_nids;
84 hda_nid_t *adc_nids; 95 const hda_nid_t *adc_nids;
85 hda_nid_t dig_in_nid; /* digital-in NID; optional */ 96 hda_nid_t dig_in_nid; /* digital-in NID; optional */
86 97
87 unsigned int cur_adc_idx; 98 unsigned int cur_adc_idx;
@@ -89,9 +100,11 @@ struct conexant_spec {
89 unsigned int cur_adc_stream_tag; 100 unsigned int cur_adc_stream_tag;
90 unsigned int cur_adc_format; 101 unsigned int cur_adc_format;
91 102
103 const struct hda_pcm_stream *capture_stream;
104
92 /* capture source */ 105 /* capture source */
93 const struct hda_input_mux *input_mux; 106 const struct hda_input_mux *input_mux;
94 hda_nid_t *capsrc_nids; 107 const hda_nid_t *capsrc_nids;
95 unsigned int cur_mux[3]; 108 unsigned int cur_mux[3];
96 109
97 /* channel model */ 110 /* channel model */
@@ -103,20 +116,28 @@ struct conexant_spec {
103 116
104 unsigned int spdif_route; 117 unsigned int spdif_route;
105 118
106 /* jack detection */
107 struct snd_array jacks;
108
109 /* dynamic controls, init_verbs and input_mux */ 119 /* dynamic controls, init_verbs and input_mux */
110 struct auto_pin_cfg autocfg; 120 struct auto_pin_cfg autocfg;
111 struct hda_input_mux private_imux; 121 struct hda_input_mux private_imux;
122 struct imux_info imux_info[HDA_MAX_NUM_INPUTS];
123 hda_nid_t private_adc_nids[HDA_MAX_NUM_INPUTS];
112 hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; 124 hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
125 struct pin_dac_pair dac_info[8];
126 int dac_info_filled;
113 127
114 unsigned int dell_automute;
115 unsigned int port_d_mode; 128 unsigned int port_d_mode;
129 unsigned int auto_mute:1; /* used in auto-parser */
130 unsigned int detect_line:1; /* Line-out detection enabled */
131 unsigned int automute_lines:1; /* automute line-out as well */
132 unsigned int automute_hp_lo:1; /* both HP and LO available */
133 unsigned int dell_automute:1;
116 unsigned int dell_vostro:1; 134 unsigned int dell_vostro:1;
117 unsigned int ideapad:1; 135 unsigned int ideapad:1;
118 unsigned int thinkpad:1; 136 unsigned int thinkpad:1;
119 unsigned int hp_laptop:1; 137 unsigned int hp_laptop:1;
138 unsigned int asus:1;
139
140 unsigned int adc_switching:1;
120 141
121 unsigned int ext_mic_present; 142 unsigned int ext_mic_present;
122 unsigned int recording; 143 unsigned int recording;
@@ -226,7 +247,7 @@ static int conexant_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
226 247
227 248
228 249
229static struct hda_pcm_stream conexant_pcm_analog_playback = { 250static const struct hda_pcm_stream conexant_pcm_analog_playback = {
230 .substreams = 1, 251 .substreams = 1,
231 .channels_min = 2, 252 .channels_min = 2,
232 .channels_max = 2, 253 .channels_max = 2,
@@ -238,7 +259,7 @@ static struct hda_pcm_stream conexant_pcm_analog_playback = {
238 }, 259 },
239}; 260};
240 261
241static struct hda_pcm_stream conexant_pcm_analog_capture = { 262static const struct hda_pcm_stream conexant_pcm_analog_capture = {
242 .substreams = 1, 263 .substreams = 1,
243 .channels_min = 2, 264 .channels_min = 2,
244 .channels_max = 2, 265 .channels_max = 2,
@@ -250,7 +271,7 @@ static struct hda_pcm_stream conexant_pcm_analog_capture = {
250}; 271};
251 272
252 273
253static struct hda_pcm_stream conexant_pcm_digital_playback = { 274static const struct hda_pcm_stream conexant_pcm_digital_playback = {
254 .substreams = 1, 275 .substreams = 1,
255 .channels_min = 2, 276 .channels_min = 2,
256 .channels_max = 2, 277 .channels_max = 2,
@@ -262,7 +283,7 @@ static struct hda_pcm_stream conexant_pcm_digital_playback = {
262 }, 283 },
263}; 284};
264 285
265static struct hda_pcm_stream conexant_pcm_digital_capture = { 286static const struct hda_pcm_stream conexant_pcm_digital_capture = {
266 .substreams = 1, 287 .substreams = 1,
267 .channels_min = 2, 288 .channels_min = 2,
268 .channels_max = 2, 289 .channels_max = 2,
@@ -293,7 +314,7 @@ static int cx5051_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
293 return 0; 314 return 0;
294} 315}
295 316
296static struct hda_pcm_stream cx5051_pcm_analog_capture = { 317static const struct hda_pcm_stream cx5051_pcm_analog_capture = {
297 .substreams = 1, 318 .substreams = 1,
298 .channels_min = 2, 319 .channels_min = 2,
299 .channels_max = 2, 320 .channels_max = 2,
@@ -318,13 +339,19 @@ static int conexant_build_pcms(struct hda_codec *codec)
318 spec->multiout.max_channels; 339 spec->multiout.max_channels;
319 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 340 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
320 spec->multiout.dac_nids[0]; 341 spec->multiout.dac_nids[0];
321 if (codec->vendor_id == 0x14f15051) 342 if (spec->capture_stream)
322 info->stream[SNDRV_PCM_STREAM_CAPTURE] = 343 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *spec->capture_stream;
323 cx5051_pcm_analog_capture; 344 else {
324 else 345 if (codec->vendor_id == 0x14f15051)
325 info->stream[SNDRV_PCM_STREAM_CAPTURE] = 346 info->stream[SNDRV_PCM_STREAM_CAPTURE] =
326 conexant_pcm_analog_capture; 347 cx5051_pcm_analog_capture;
327 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adc_nids; 348 else {
349 info->stream[SNDRV_PCM_STREAM_CAPTURE] =
350 conexant_pcm_analog_capture;
351 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
352 spec->num_adc_nids;
353 }
354 }
328 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0]; 355 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
329 356
330 if (spec->multiout.dig_out_nid) { 357 if (spec->multiout.dig_out_nid) {
@@ -342,6 +369,8 @@ static int conexant_build_pcms(struct hda_codec *codec)
342 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = 369 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
343 spec->dig_in_nid; 370 spec->dig_in_nid;
344 } 371 }
372 if (spec->slave_dig_outs[0])
373 codec->slave_dig_outs = spec->slave_dig_outs;
345 } 374 }
346 375
347 return 0; 376 return 0;
@@ -379,65 +408,9 @@ static int conexant_mux_enum_put(struct snd_kcontrol *kcontrol,
379 &spec->cur_mux[adc_idx]); 408 &spec->cur_mux[adc_idx]);
380} 409}
381 410
382#ifdef CONFIG_SND_HDA_INPUT_JACK
383static void conexant_free_jack_priv(struct snd_jack *jack)
384{
385 struct conexant_jack *jacks = jack->private_data;
386 jacks->nid = 0;
387 jacks->jack = NULL;
388}
389
390static int conexant_add_jack(struct hda_codec *codec,
391 hda_nid_t nid, int type)
392{
393 struct conexant_spec *spec;
394 struct conexant_jack *jack;
395 const char *name;
396 int err;
397
398 spec = codec->spec;
399 snd_array_init(&spec->jacks, sizeof(*jack), 32);
400 jack = snd_array_new(&spec->jacks);
401 name = (type == SND_JACK_HEADPHONE) ? "Headphone" : "Mic" ;
402
403 if (!jack)
404 return -ENOMEM;
405
406 jack->nid = nid;
407 jack->type = type;
408
409 err = snd_jack_new(codec->bus->card, name, type, &jack->jack);
410 if (err < 0)
411 return err;
412 jack->jack->private_data = jack;
413 jack->jack->private_free = conexant_free_jack_priv;
414 return 0;
415}
416
417static void conexant_report_jack(struct hda_codec *codec, hda_nid_t nid)
418{
419 struct conexant_spec *spec = codec->spec;
420 struct conexant_jack *jacks = spec->jacks.list;
421
422 if (jacks) {
423 int i;
424 for (i = 0; i < spec->jacks.used; i++) {
425 if (jacks->nid == nid) {
426 unsigned int present;
427 present = snd_hda_jack_detect(codec, nid);
428
429 present = (present) ? jacks->type : 0 ;
430
431 snd_jack_report(jacks->jack,
432 present);
433 }
434 jacks++;
435 }
436 }
437}
438
439static int conexant_init_jacks(struct hda_codec *codec) 411static int conexant_init_jacks(struct hda_codec *codec)
440{ 412{
413#ifdef CONFIG_SND_HDA_INPUT_JACK
441 struct conexant_spec *spec = codec->spec; 414 struct conexant_spec *spec = codec->spec;
442 int i; 415 int i;
443 416
@@ -449,15 +422,15 @@ static int conexant_init_jacks(struct hda_codec *codec)
449 int err = 0; 422 int err = 0;
450 switch (hv->param ^ AC_USRSP_EN) { 423 switch (hv->param ^ AC_USRSP_EN) {
451 case CONEXANT_HP_EVENT: 424 case CONEXANT_HP_EVENT:
452 err = conexant_add_jack(codec, hv->nid, 425 err = snd_hda_input_jack_add(codec, hv->nid,
453 SND_JACK_HEADPHONE); 426 SND_JACK_HEADPHONE, NULL);
454 conexant_report_jack(codec, hv->nid); 427 snd_hda_input_jack_report(codec, hv->nid);
455 break; 428 break;
456 case CXT5051_PORTC_EVENT: 429 case CXT5051_PORTC_EVENT:
457 case CONEXANT_MIC_EVENT: 430 case CONEXANT_MIC_EVENT:
458 err = conexant_add_jack(codec, hv->nid, 431 err = snd_hda_input_jack_add(codec, hv->nid,
459 SND_JACK_MICROPHONE); 432 SND_JACK_MICROPHONE, NULL);
460 conexant_report_jack(codec, hv->nid); 433 snd_hda_input_jack_report(codec, hv->nid);
461 break; 434 break;
462 } 435 }
463 if (err < 0) 436 if (err < 0)
@@ -465,19 +438,9 @@ static int conexant_init_jacks(struct hda_codec *codec)
465 ++hv; 438 ++hv;
466 } 439 }
467 } 440 }
468 return 0; 441#endif /* CONFIG_SND_HDA_INPUT_JACK */
469
470}
471#else
472static inline void conexant_report_jack(struct hda_codec *codec, hda_nid_t nid)
473{
474}
475
476static inline int conexant_init_jacks(struct hda_codec *codec)
477{
478 return 0; 442 return 0;
479} 443}
480#endif
481 444
482static int conexant_init(struct hda_codec *codec) 445static int conexant_init(struct hda_codec *codec)
483{ 446{
@@ -491,23 +454,12 @@ static int conexant_init(struct hda_codec *codec)
491 454
492static void conexant_free(struct hda_codec *codec) 455static void conexant_free(struct hda_codec *codec)
493{ 456{
494#ifdef CONFIG_SND_HDA_INPUT_JACK 457 snd_hda_input_jack_free(codec);
495 struct conexant_spec *spec = codec->spec;
496 if (spec->jacks.list) {
497 struct conexant_jack *jacks = spec->jacks.list;
498 int i;
499 for (i = 0; i < spec->jacks.used; i++, jacks++) {
500 if (jacks->jack)
501 snd_device_free(codec->bus->card, jacks->jack);
502 }
503 snd_array_free(&spec->jacks);
504 }
505#endif
506 snd_hda_detach_beep_device(codec); 458 snd_hda_detach_beep_device(codec);
507 kfree(codec->spec); 459 kfree(codec->spec);
508} 460}
509 461
510static struct snd_kcontrol_new cxt_capture_mixers[] = { 462static const struct snd_kcontrol_new cxt_capture_mixers[] = {
511 { 463 {
512 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 464 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
513 .name = "Capture Source", 465 .name = "Capture Source",
@@ -520,22 +472,28 @@ static struct snd_kcontrol_new cxt_capture_mixers[] = {
520 472
521#ifdef CONFIG_SND_HDA_INPUT_BEEP 473#ifdef CONFIG_SND_HDA_INPUT_BEEP
522/* additional beep mixers; the actual parameters are overwritten at build */ 474/* additional beep mixers; the actual parameters are overwritten at build */
523static struct snd_kcontrol_new cxt_beep_mixer[] = { 475static const struct snd_kcontrol_new cxt_beep_mixer[] = {
524 HDA_CODEC_VOLUME_MONO("Beep Playback Volume", 0, 1, 0, HDA_OUTPUT), 476 HDA_CODEC_VOLUME_MONO("Beep Playback Volume", 0, 1, 0, HDA_OUTPUT),
525 HDA_CODEC_MUTE_BEEP_MONO("Beep Playback Switch", 0, 1, 0, HDA_OUTPUT), 477 HDA_CODEC_MUTE_BEEP_MONO("Beep Playback Switch", 0, 1, 0, HDA_OUTPUT),
526 { } /* end */ 478 { } /* end */
527}; 479};
528#endif 480#endif
529 481
530static const char *slave_vols[] = { 482static const char * const slave_vols[] = {
531 "Headphone Playback Volume", 483 "Headphone Playback Volume",
532 "Speaker Playback Volume", 484 "Speaker Playback Volume",
485 "Front Playback Volume",
486 "Surround Playback Volume",
487 "CLFE Playback Volume",
533 NULL 488 NULL
534}; 489};
535 490
536static const char *slave_sws[] = { 491static const char * const slave_sws[] = {
537 "Headphone Playback Switch", 492 "Headphone Playback Switch",
538 "Speaker Playback Switch", 493 "Speaker Playback Switch",
494 "Front Playback Switch",
495 "Surround Playback Switch",
496 "CLFE Playback Switch",
539 NULL 497 NULL
540}; 498};
541 499
@@ -595,7 +553,7 @@ static int conexant_build_controls(struct hda_codec *codec)
595#ifdef CONFIG_SND_HDA_INPUT_BEEP 553#ifdef CONFIG_SND_HDA_INPUT_BEEP
596 /* create beep controls if needed */ 554 /* create beep controls if needed */
597 if (spec->beep_amp) { 555 if (spec->beep_amp) {
598 struct snd_kcontrol_new *knew; 556 const struct snd_kcontrol_new *knew;
599 for (knew = cxt_beep_mixer; knew->name; knew++) { 557 for (knew = cxt_beep_mixer; knew->name; knew++) {
600 struct snd_kcontrol *kctl; 558 struct snd_kcontrol *kctl;
601 kctl = snd_ctl_new1(knew, codec); 559 kctl = snd_ctl_new1(knew, codec);
@@ -620,7 +578,7 @@ static int conexant_suspend(struct hda_codec *codec, pm_message_t state)
620} 578}
621#endif 579#endif
622 580
623static struct hda_codec_ops conexant_patch_ops = { 581static const struct hda_codec_ops conexant_patch_ops = {
624 .build_controls = conexant_build_controls, 582 .build_controls = conexant_build_controls,
625 .build_pcms = conexant_build_pcms, 583 .build_pcms = conexant_build_pcms,
626 .init = conexant_init, 584 .init = conexant_init,
@@ -638,6 +596,7 @@ static struct hda_codec_ops conexant_patch_ops = {
638#define set_beep_amp(spec, nid, idx, dir) /* NOP */ 596#define set_beep_amp(spec, nid, idx, dir) /* NOP */
639#endif 597#endif
640 598
599static int patch_conexant_auto(struct hda_codec *codec);
641/* 600/*
642 * EAPD control 601 * EAPD control
643 * the private value = nid | (invert << 8) 602 * the private value = nid | (invert << 8)
@@ -736,16 +695,16 @@ static int conexant_ch_mode_put(struct snd_kcontrol *kcontrol,
736 695
737/* Conexant 5045 specific */ 696/* Conexant 5045 specific */
738 697
739static hda_nid_t cxt5045_dac_nids[1] = { 0x19 }; 698static const hda_nid_t cxt5045_dac_nids[1] = { 0x19 };
740static hda_nid_t cxt5045_adc_nids[1] = { 0x1a }; 699static const hda_nid_t cxt5045_adc_nids[1] = { 0x1a };
741static hda_nid_t cxt5045_capsrc_nids[1] = { 0x1a }; 700static const hda_nid_t cxt5045_capsrc_nids[1] = { 0x1a };
742#define CXT5045_SPDIF_OUT 0x18 701#define CXT5045_SPDIF_OUT 0x18
743 702
744static struct hda_channel_mode cxt5045_modes[1] = { 703static const struct hda_channel_mode cxt5045_modes[1] = {
745 { 2, NULL }, 704 { 2, NULL },
746}; 705};
747 706
748static struct hda_input_mux cxt5045_capture_source = { 707static const struct hda_input_mux cxt5045_capture_source = {
749 .num_items = 2, 708 .num_items = 2,
750 .items = { 709 .items = {
751 { "IntMic", 0x1 }, 710 { "IntMic", 0x1 },
@@ -753,7 +712,7 @@ static struct hda_input_mux cxt5045_capture_source = {
753 } 712 }
754}; 713};
755 714
756static struct hda_input_mux cxt5045_capture_source_benq = { 715static const struct hda_input_mux cxt5045_capture_source_benq = {
757 .num_items = 5, 716 .num_items = 5,
758 .items = { 717 .items = {
759 { "IntMic", 0x1 }, 718 { "IntMic", 0x1 },
@@ -764,7 +723,7 @@ static struct hda_input_mux cxt5045_capture_source_benq = {
764 } 723 }
765}; 724};
766 725
767static struct hda_input_mux cxt5045_capture_source_hp530 = { 726static const struct hda_input_mux cxt5045_capture_source_hp530 = {
768 .num_items = 2, 727 .num_items = 2,
769 .items = { 728 .items = {
770 { "ExtMic", 0x1 }, 729 { "ExtMic", 0x1 },
@@ -797,7 +756,7 @@ static int cxt5045_hp_master_sw_put(struct snd_kcontrol *kcontrol,
797} 756}
798 757
799/* bind volumes of both NID 0x10 and 0x11 */ 758/* bind volumes of both NID 0x10 and 0x11 */
800static struct hda_bind_ctls cxt5045_hp_bind_master_vol = { 759static const struct hda_bind_ctls cxt5045_hp_bind_master_vol = {
801 .ops = &snd_hda_bind_vol, 760 .ops = &snd_hda_bind_vol,
802 .values = { 761 .values = {
803 HDA_COMPOSE_AMP_VAL(0x10, 3, 0, HDA_OUTPUT), 762 HDA_COMPOSE_AMP_VAL(0x10, 3, 0, HDA_OUTPUT),
@@ -809,12 +768,12 @@ static struct hda_bind_ctls cxt5045_hp_bind_master_vol = {
809/* toggle input of built-in and mic jack appropriately */ 768/* toggle input of built-in and mic jack appropriately */
810static void cxt5045_hp_automic(struct hda_codec *codec) 769static void cxt5045_hp_automic(struct hda_codec *codec)
811{ 770{
812 static struct hda_verb mic_jack_on[] = { 771 static const struct hda_verb mic_jack_on[] = {
813 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 772 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
814 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, 773 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
815 {} 774 {}
816 }; 775 };
817 static struct hda_verb mic_jack_off[] = { 776 static const struct hda_verb mic_jack_off[] = {
818 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, 777 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
819 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, 778 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
820 {} 779 {}
@@ -858,17 +817,17 @@ static void cxt5045_hp_unsol_event(struct hda_codec *codec,
858 } 817 }
859} 818}
860 819
861static struct snd_kcontrol_new cxt5045_mixers[] = { 820static const struct snd_kcontrol_new cxt5045_mixers[] = {
862 HDA_CODEC_VOLUME("Int Mic Capture Volume", 0x1a, 0x01, HDA_INPUT), 821 HDA_CODEC_VOLUME("Internal Mic Capture Volume", 0x1a, 0x01, HDA_INPUT),
863 HDA_CODEC_MUTE("Int Mic Capture Switch", 0x1a, 0x01, HDA_INPUT), 822 HDA_CODEC_MUTE("Internal Mic Capture Switch", 0x1a, 0x01, HDA_INPUT),
864 HDA_CODEC_VOLUME("Ext Mic Capture Volume", 0x1a, 0x02, HDA_INPUT), 823 HDA_CODEC_VOLUME("Mic Capture Volume", 0x1a, 0x02, HDA_INPUT),
865 HDA_CODEC_MUTE("Ext Mic Capture Switch", 0x1a, 0x02, HDA_INPUT), 824 HDA_CODEC_MUTE("Mic Capture Switch", 0x1a, 0x02, HDA_INPUT),
866 HDA_CODEC_VOLUME("PCM Playback Volume", 0x17, 0x0, HDA_INPUT), 825 HDA_CODEC_VOLUME("PCM Playback Volume", 0x17, 0x0, HDA_INPUT),
867 HDA_CODEC_MUTE("PCM Playback Switch", 0x17, 0x0, HDA_INPUT), 826 HDA_CODEC_MUTE("PCM Playback Switch", 0x17, 0x0, HDA_INPUT),
868 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x17, 0x1, HDA_INPUT), 827 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0x1, HDA_INPUT),
869 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x17, 0x1, HDA_INPUT), 828 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0x1, HDA_INPUT),
870 HDA_CODEC_VOLUME("Ext Mic Playback Volume", 0x17, 0x2, HDA_INPUT), 829 HDA_CODEC_VOLUME("Mic Playback Volume", 0x17, 0x2, HDA_INPUT),
871 HDA_CODEC_MUTE("Ext Mic Playback Switch", 0x17, 0x2, HDA_INPUT), 830 HDA_CODEC_MUTE("Mic Playback Switch", 0x17, 0x2, HDA_INPUT),
872 HDA_BIND_VOL("Master Playback Volume", &cxt5045_hp_bind_master_vol), 831 HDA_BIND_VOL("Master Playback Volume", &cxt5045_hp_bind_master_vol),
873 { 832 {
874 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 833 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -882,7 +841,7 @@ static struct snd_kcontrol_new cxt5045_mixers[] = {
882 {} 841 {}
883}; 842};
884 843
885static struct snd_kcontrol_new cxt5045_benq_mixers[] = { 844static const struct snd_kcontrol_new cxt5045_benq_mixers[] = {
886 HDA_CODEC_VOLUME("CD Capture Volume", 0x1a, 0x04, HDA_INPUT), 845 HDA_CODEC_VOLUME("CD Capture Volume", 0x1a, 0x04, HDA_INPUT),
887 HDA_CODEC_MUTE("CD Capture Switch", 0x1a, 0x04, HDA_INPUT), 846 HDA_CODEC_MUTE("CD Capture Switch", 0x1a, 0x04, HDA_INPUT),
888 HDA_CODEC_VOLUME("CD Playback Volume", 0x17, 0x4, HDA_INPUT), 847 HDA_CODEC_VOLUME("CD Playback Volume", 0x17, 0x4, HDA_INPUT),
@@ -899,17 +858,17 @@ static struct snd_kcontrol_new cxt5045_benq_mixers[] = {
899 {} 858 {}
900}; 859};
901 860
902static struct snd_kcontrol_new cxt5045_mixers_hp530[] = { 861static const struct snd_kcontrol_new cxt5045_mixers_hp530[] = {
903 HDA_CODEC_VOLUME("Int Mic Capture Volume", 0x1a, 0x02, HDA_INPUT), 862 HDA_CODEC_VOLUME("Internal Mic Capture Volume", 0x1a, 0x02, HDA_INPUT),
904 HDA_CODEC_MUTE("Int Mic Capture Switch", 0x1a, 0x02, HDA_INPUT), 863 HDA_CODEC_MUTE("Internal Mic Capture Switch", 0x1a, 0x02, HDA_INPUT),
905 HDA_CODEC_VOLUME("Ext Mic Capture Volume", 0x1a, 0x01, HDA_INPUT), 864 HDA_CODEC_VOLUME("Mic Capture Volume", 0x1a, 0x01, HDA_INPUT),
906 HDA_CODEC_MUTE("Ext Mic Capture Switch", 0x1a, 0x01, HDA_INPUT), 865 HDA_CODEC_MUTE("Mic Capture Switch", 0x1a, 0x01, HDA_INPUT),
907 HDA_CODEC_VOLUME("PCM Playback Volume", 0x17, 0x0, HDA_INPUT), 866 HDA_CODEC_VOLUME("PCM Playback Volume", 0x17, 0x0, HDA_INPUT),
908 HDA_CODEC_MUTE("PCM Playback Switch", 0x17, 0x0, HDA_INPUT), 867 HDA_CODEC_MUTE("PCM Playback Switch", 0x17, 0x0, HDA_INPUT),
909 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x17, 0x2, HDA_INPUT), 868 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0x2, HDA_INPUT),
910 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x17, 0x2, HDA_INPUT), 869 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0x2, HDA_INPUT),
911 HDA_CODEC_VOLUME("Ext Mic Playback Volume", 0x17, 0x1, HDA_INPUT), 870 HDA_CODEC_VOLUME("Mic Playback Volume", 0x17, 0x1, HDA_INPUT),
912 HDA_CODEC_MUTE("Ext Mic Playback Switch", 0x17, 0x1, HDA_INPUT), 871 HDA_CODEC_MUTE("Mic Playback Switch", 0x17, 0x1, HDA_INPUT),
913 HDA_BIND_VOL("Master Playback Volume", &cxt5045_hp_bind_master_vol), 872 HDA_BIND_VOL("Master Playback Volume", &cxt5045_hp_bind_master_vol),
914 { 873 {
915 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 874 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -923,7 +882,7 @@ static struct snd_kcontrol_new cxt5045_mixers_hp530[] = {
923 {} 882 {}
924}; 883};
925 884
926static struct hda_verb cxt5045_init_verbs[] = { 885static const struct hda_verb cxt5045_init_verbs[] = {
927 /* Line in, Mic */ 886 /* Line in, Mic */
928 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 }, 887 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 },
929 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 }, 888 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 },
@@ -937,7 +896,7 @@ static struct hda_verb cxt5045_init_verbs[] = {
937 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 896 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
938 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 897 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
939 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 898 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
940 /* Record selector: Int mic */ 899 /* Record selector: Internal mic */
941 {0x1a, AC_VERB_SET_CONNECT_SEL,0x1}, 900 {0x1a, AC_VERB_SET_CONNECT_SEL,0x1},
942 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 901 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE,
943 AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, 902 AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17},
@@ -949,8 +908,8 @@ static struct hda_verb cxt5045_init_verbs[] = {
949 { } /* end */ 908 { } /* end */
950}; 909};
951 910
952static struct hda_verb cxt5045_benq_init_verbs[] = { 911static const struct hda_verb cxt5045_benq_init_verbs[] = {
953 /* Int Mic, Mic */ 912 /* Internal Mic, Mic */
954 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 }, 913 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 },
955 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 }, 914 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 },
956 /* Line In,HP, Amp */ 915 /* Line In,HP, Amp */
@@ -963,7 +922,7 @@ static struct hda_verb cxt5045_benq_init_verbs[] = {
963 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, 922 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
964 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, 923 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
965 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 924 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
966 /* Record selector: Int mic */ 925 /* Record selector: Internal mic */
967 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x1}, 926 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x1},
968 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 927 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE,
969 AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, 928 AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17},
@@ -975,13 +934,13 @@ static struct hda_verb cxt5045_benq_init_verbs[] = {
975 { } /* end */ 934 { } /* end */
976}; 935};
977 936
978static struct hda_verb cxt5045_hp_sense_init_verbs[] = { 937static const struct hda_verb cxt5045_hp_sense_init_verbs[] = {
979 /* pin sensing on HP jack */ 938 /* pin sensing on HP jack */
980 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, 939 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
981 { } /* end */ 940 { } /* end */
982}; 941};
983 942
984static struct hda_verb cxt5045_mic_sense_init_verbs[] = { 943static const struct hda_verb cxt5045_mic_sense_init_verbs[] = {
985 /* pin sensing on HP jack */ 944 /* pin sensing on HP jack */
986 {0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, 945 {0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
987 { } /* end */ 946 { } /* end */
@@ -991,7 +950,7 @@ static struct hda_verb cxt5045_mic_sense_init_verbs[] = {
991/* Test configuration for debugging, modelled after the ALC260 test 950/* Test configuration for debugging, modelled after the ALC260 test
992 * configuration. 951 * configuration.
993 */ 952 */
994static struct hda_input_mux cxt5045_test_capture_source = { 953static const struct hda_input_mux cxt5045_test_capture_source = {
995 .num_items = 5, 954 .num_items = 5,
996 .items = { 955 .items = {
997 { "MIXER", 0x0 }, 956 { "MIXER", 0x0 },
@@ -1002,7 +961,7 @@ static struct hda_input_mux cxt5045_test_capture_source = {
1002 }, 961 },
1003}; 962};
1004 963
1005static struct snd_kcontrol_new cxt5045_test_mixer[] = { 964static const struct snd_kcontrol_new cxt5045_test_mixer[] = {
1006 965
1007 /* Output controls */ 966 /* Output controls */
1008 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x10, 0x0, HDA_OUTPUT), 967 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x10, 0x0, HDA_OUTPUT),
@@ -1052,7 +1011,7 @@ static struct snd_kcontrol_new cxt5045_test_mixer[] = {
1052 { } /* end */ 1011 { } /* end */
1053}; 1012};
1054 1013
1055static struct hda_verb cxt5045_test_init_verbs[] = { 1014static const struct hda_verb cxt5045_test_init_verbs[] = {
1056 /* Set connections */ 1015 /* Set connections */
1057 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 }, 1016 { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
1058 { 0x11, AC_VERB_SET_CONNECT_SEL, 0x0 }, 1017 { 0x11, AC_VERB_SET_CONNECT_SEL, 0x0 },
@@ -1121,10 +1080,11 @@ enum {
1121#ifdef CONFIG_SND_DEBUG 1080#ifdef CONFIG_SND_DEBUG
1122 CXT5045_TEST, 1081 CXT5045_TEST,
1123#endif 1082#endif
1083 CXT5045_AUTO,
1124 CXT5045_MODELS 1084 CXT5045_MODELS
1125}; 1085};
1126 1086
1127static const char *cxt5045_models[CXT5045_MODELS] = { 1087static const char * const cxt5045_models[CXT5045_MODELS] = {
1128 [CXT5045_LAPTOP_HPSENSE] = "laptop-hpsense", 1088 [CXT5045_LAPTOP_HPSENSE] = "laptop-hpsense",
1129 [CXT5045_LAPTOP_MICSENSE] = "laptop-micsense", 1089 [CXT5045_LAPTOP_MICSENSE] = "laptop-micsense",
1130 [CXT5045_LAPTOP_HPMICSENSE] = "laptop-hpmicsense", 1090 [CXT5045_LAPTOP_HPMICSENSE] = "laptop-hpmicsense",
@@ -1133,9 +1093,10 @@ static const char *cxt5045_models[CXT5045_MODELS] = {
1133#ifdef CONFIG_SND_DEBUG 1093#ifdef CONFIG_SND_DEBUG
1134 [CXT5045_TEST] = "test", 1094 [CXT5045_TEST] = "test",
1135#endif 1095#endif
1096 [CXT5045_AUTO] = "auto",
1136}; 1097};
1137 1098
1138static struct snd_pci_quirk cxt5045_cfg_tbl[] = { 1099static const struct snd_pci_quirk cxt5045_cfg_tbl[] = {
1139 SND_PCI_QUIRK(0x103c, 0x30d5, "HP 530", CXT5045_LAPTOP_HP530), 1100 SND_PCI_QUIRK(0x103c, 0x30d5, "HP 530", CXT5045_LAPTOP_HP530),
1140 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3000, "HP DV Series", 1101 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3000, "HP DV Series",
1141 CXT5045_LAPTOP_HPSENSE), 1102 CXT5045_LAPTOP_HPSENSE),
@@ -1159,6 +1120,16 @@ static int patch_cxt5045(struct hda_codec *codec)
1159 struct conexant_spec *spec; 1120 struct conexant_spec *spec;
1160 int board_config; 1121 int board_config;
1161 1122
1123 board_config = snd_hda_check_board_config(codec, CXT5045_MODELS,
1124 cxt5045_models,
1125 cxt5045_cfg_tbl);
1126#if 0 /* use the old method just for safety */
1127 if (board_config < 0)
1128 board_config = CXT5045_AUTO;
1129#endif
1130 if (board_config == CXT5045_AUTO)
1131 return patch_conexant_auto(codec);
1132
1162 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 1133 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1163 if (!spec) 1134 if (!spec)
1164 return -ENOMEM; 1135 return -ENOMEM;
@@ -1185,9 +1156,6 @@ static int patch_cxt5045(struct hda_codec *codec)
1185 1156
1186 codec->patch_ops = conexant_patch_ops; 1157 codec->patch_ops = conexant_patch_ops;
1187 1158
1188 board_config = snd_hda_check_board_config(codec, CXT5045_MODELS,
1189 cxt5045_models,
1190 cxt5045_cfg_tbl);
1191 switch (board_config) { 1159 switch (board_config) {
1192 case CXT5045_LAPTOP_HPSENSE: 1160 case CXT5045_LAPTOP_HPSENSE:
1193 codec->patch_ops.unsol_event = cxt5045_hp_unsol_event; 1161 codec->patch_ops.unsol_event = cxt5045_hp_unsol_event;
@@ -1270,15 +1238,15 @@ static int patch_cxt5045(struct hda_codec *codec)
1270/* Conexant 5047 specific */ 1238/* Conexant 5047 specific */
1271#define CXT5047_SPDIF_OUT 0x11 1239#define CXT5047_SPDIF_OUT 0x11
1272 1240
1273static hda_nid_t cxt5047_dac_nids[1] = { 0x10 }; /* 0x1c */ 1241static const hda_nid_t cxt5047_dac_nids[1] = { 0x10 }; /* 0x1c */
1274static hda_nid_t cxt5047_adc_nids[1] = { 0x12 }; 1242static const hda_nid_t cxt5047_adc_nids[1] = { 0x12 };
1275static hda_nid_t cxt5047_capsrc_nids[1] = { 0x1a }; 1243static const hda_nid_t cxt5047_capsrc_nids[1] = { 0x1a };
1276 1244
1277static struct hda_channel_mode cxt5047_modes[1] = { 1245static const struct hda_channel_mode cxt5047_modes[1] = {
1278 { 2, NULL }, 1246 { 2, NULL },
1279}; 1247};
1280 1248
1281static struct hda_input_mux cxt5047_toshiba_capture_source = { 1249static const struct hda_input_mux cxt5047_toshiba_capture_source = {
1282 .num_items = 2, 1250 .num_items = 2,
1283 .items = { 1251 .items = {
1284 { "ExtMic", 0x2 }, 1252 { "ExtMic", 0x2 },
@@ -1330,12 +1298,12 @@ static void cxt5047_hp_automute(struct hda_codec *codec)
1330/* toggle input of built-in and mic jack appropriately */ 1298/* toggle input of built-in and mic jack appropriately */
1331static void cxt5047_hp_automic(struct hda_codec *codec) 1299static void cxt5047_hp_automic(struct hda_codec *codec)
1332{ 1300{
1333 static struct hda_verb mic_jack_on[] = { 1301 static const struct hda_verb mic_jack_on[] = {
1334 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1302 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1335 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1303 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1336 {} 1304 {}
1337 }; 1305 };
1338 static struct hda_verb mic_jack_off[] = { 1306 static const struct hda_verb mic_jack_off[] = {
1339 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 1307 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1340 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1308 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1341 {} 1309 {}
@@ -1363,10 +1331,10 @@ static void cxt5047_hp_unsol_event(struct hda_codec *codec,
1363 } 1331 }
1364} 1332}
1365 1333
1366static struct snd_kcontrol_new cxt5047_base_mixers[] = { 1334static const struct snd_kcontrol_new cxt5047_base_mixers[] = {
1367 HDA_CODEC_VOLUME("Mic Playback Volume", 0x19, 0x02, HDA_INPUT), 1335 HDA_CODEC_VOLUME("Mic Playback Volume", 0x19, 0x02, HDA_INPUT),
1368 HDA_CODEC_MUTE("Mic Playback Switch", 0x19, 0x02, HDA_INPUT), 1336 HDA_CODEC_MUTE("Mic Playback Switch", 0x19, 0x02, HDA_INPUT),
1369 HDA_CODEC_VOLUME("Mic Boost", 0x1a, 0x0, HDA_OUTPUT), 1337 HDA_CODEC_VOLUME("Mic Boost Volume", 0x1a, 0x0, HDA_OUTPUT),
1370 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT), 1338 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT),
1371 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT), 1339 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT),
1372 HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT), 1340 HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT),
@@ -1383,19 +1351,19 @@ static struct snd_kcontrol_new cxt5047_base_mixers[] = {
1383 {} 1351 {}
1384}; 1352};
1385 1353
1386static struct snd_kcontrol_new cxt5047_hp_spk_mixers[] = { 1354static const struct snd_kcontrol_new cxt5047_hp_spk_mixers[] = {
1387 /* See the note in cxt5047_hp_master_sw_put */ 1355 /* See the note in cxt5047_hp_master_sw_put */
1388 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x01, HDA_OUTPUT), 1356 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x01, HDA_OUTPUT),
1389 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x13, 0x00, HDA_OUTPUT), 1357 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x13, 0x00, HDA_OUTPUT),
1390 {} 1358 {}
1391}; 1359};
1392 1360
1393static struct snd_kcontrol_new cxt5047_hp_only_mixers[] = { 1361static const struct snd_kcontrol_new cxt5047_hp_only_mixers[] = {
1394 HDA_CODEC_VOLUME("Master Playback Volume", 0x13, 0x00, HDA_OUTPUT), 1362 HDA_CODEC_VOLUME("Master Playback Volume", 0x13, 0x00, HDA_OUTPUT),
1395 { } /* end */ 1363 { } /* end */
1396}; 1364};
1397 1365
1398static struct hda_verb cxt5047_init_verbs[] = { 1366static const struct hda_verb cxt5047_init_verbs[] = {
1399 /* Line in, Mic, Built-in Mic */ 1367 /* Line in, Mic, Built-in Mic */
1400 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, 1368 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
1401 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 }, 1369 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 },
@@ -1422,7 +1390,7 @@ static struct hda_verb cxt5047_init_verbs[] = {
1422}; 1390};
1423 1391
1424/* configuration for Toshiba Laptops */ 1392/* configuration for Toshiba Laptops */
1425static struct hda_verb cxt5047_toshiba_init_verbs[] = { 1393static const struct hda_verb cxt5047_toshiba_init_verbs[] = {
1426 {0x13, AC_VERB_SET_EAPD_BTLENABLE, 0x0}, /* default off */ 1394 {0x13, AC_VERB_SET_EAPD_BTLENABLE, 0x0}, /* default off */
1427 {} 1395 {}
1428}; 1396};
@@ -1431,7 +1399,7 @@ static struct hda_verb cxt5047_toshiba_init_verbs[] = {
1431 * configuration. 1399 * configuration.
1432 */ 1400 */
1433#ifdef CONFIG_SND_DEBUG 1401#ifdef CONFIG_SND_DEBUG
1434static struct hda_input_mux cxt5047_test_capture_source = { 1402static const struct hda_input_mux cxt5047_test_capture_source = {
1435 .num_items = 4, 1403 .num_items = 4,
1436 .items = { 1404 .items = {
1437 { "LINE1 pin", 0x0 }, 1405 { "LINE1 pin", 0x0 },
@@ -1441,7 +1409,7 @@ static struct hda_input_mux cxt5047_test_capture_source = {
1441 }, 1409 },
1442}; 1410};
1443 1411
1444static struct snd_kcontrol_new cxt5047_test_mixer[] = { 1412static const struct snd_kcontrol_new cxt5047_test_mixer[] = {
1445 1413
1446 /* Output only controls */ 1414 /* Output only controls */
1447 HDA_CODEC_VOLUME("OutAmp-1 Volume", 0x10, 0x0, HDA_OUTPUT), 1415 HDA_CODEC_VOLUME("OutAmp-1 Volume", 0x10, 0x0, HDA_OUTPUT),
@@ -1494,7 +1462,7 @@ static struct snd_kcontrol_new cxt5047_test_mixer[] = {
1494 { } /* end */ 1462 { } /* end */
1495}; 1463};
1496 1464
1497static struct hda_verb cxt5047_test_init_verbs[] = { 1465static const struct hda_verb cxt5047_test_init_verbs[] = {
1498 /* Enable retasking pins as output, initially without power amp */ 1466 /* Enable retasking pins as output, initially without power amp */
1499 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1467 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1500 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1468 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
@@ -1566,19 +1534,21 @@ enum {
1566#ifdef CONFIG_SND_DEBUG 1534#ifdef CONFIG_SND_DEBUG
1567 CXT5047_TEST, 1535 CXT5047_TEST,
1568#endif 1536#endif
1537 CXT5047_AUTO,
1569 CXT5047_MODELS 1538 CXT5047_MODELS
1570}; 1539};
1571 1540
1572static const char *cxt5047_models[CXT5047_MODELS] = { 1541static const char * const cxt5047_models[CXT5047_MODELS] = {
1573 [CXT5047_LAPTOP] = "laptop", 1542 [CXT5047_LAPTOP] = "laptop",
1574 [CXT5047_LAPTOP_HP] = "laptop-hp", 1543 [CXT5047_LAPTOP_HP] = "laptop-hp",
1575 [CXT5047_LAPTOP_EAPD] = "laptop-eapd", 1544 [CXT5047_LAPTOP_EAPD] = "laptop-eapd",
1576#ifdef CONFIG_SND_DEBUG 1545#ifdef CONFIG_SND_DEBUG
1577 [CXT5047_TEST] = "test", 1546 [CXT5047_TEST] = "test",
1578#endif 1547#endif
1548 [CXT5047_AUTO] = "auto",
1579}; 1549};
1580 1550
1581static struct snd_pci_quirk cxt5047_cfg_tbl[] = { 1551static const struct snd_pci_quirk cxt5047_cfg_tbl[] = {
1582 SND_PCI_QUIRK(0x103c, 0x30a5, "HP DV5200T/DV8000T", CXT5047_LAPTOP_HP), 1552 SND_PCI_QUIRK(0x103c, 0x30a5, "HP DV5200T/DV8000T", CXT5047_LAPTOP_HP),
1583 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3000, "HP DV Series", 1553 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3000, "HP DV Series",
1584 CXT5047_LAPTOP), 1554 CXT5047_LAPTOP),
@@ -1591,6 +1561,16 @@ static int patch_cxt5047(struct hda_codec *codec)
1591 struct conexant_spec *spec; 1561 struct conexant_spec *spec;
1592 int board_config; 1562 int board_config;
1593 1563
1564 board_config = snd_hda_check_board_config(codec, CXT5047_MODELS,
1565 cxt5047_models,
1566 cxt5047_cfg_tbl);
1567#if 0 /* not enabled as default, as BIOS often broken for this codec */
1568 if (board_config < 0)
1569 board_config = CXT5047_AUTO;
1570#endif
1571 if (board_config == CXT5047_AUTO)
1572 return patch_conexant_auto(codec);
1573
1594 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 1574 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1595 if (!spec) 1575 if (!spec)
1596 return -ENOMEM; 1576 return -ENOMEM;
@@ -1614,9 +1594,6 @@ static int patch_cxt5047(struct hda_codec *codec)
1614 1594
1615 codec->patch_ops = conexant_patch_ops; 1595 codec->patch_ops = conexant_patch_ops;
1616 1596
1617 board_config = snd_hda_check_board_config(codec, CXT5047_MODELS,
1618 cxt5047_models,
1619 cxt5047_cfg_tbl);
1620 switch (board_config) { 1597 switch (board_config) {
1621 case CXT5047_LAPTOP: 1598 case CXT5047_LAPTOP:
1622 spec->num_mixers = 2; 1599 spec->num_mixers = 2;
@@ -1665,10 +1642,10 @@ static int patch_cxt5047(struct hda_codec *codec)
1665} 1642}
1666 1643
1667/* Conexant 5051 specific */ 1644/* Conexant 5051 specific */
1668static hda_nid_t cxt5051_dac_nids[1] = { 0x10 }; 1645static const hda_nid_t cxt5051_dac_nids[1] = { 0x10 };
1669static hda_nid_t cxt5051_adc_nids[2] = { 0x14, 0x15 }; 1646static const hda_nid_t cxt5051_adc_nids[2] = { 0x14, 0x15 };
1670 1647
1671static struct hda_channel_mode cxt5051_modes[1] = { 1648static const struct hda_channel_mode cxt5051_modes[1] = {
1672 { 2, NULL }, 1649 { 2, NULL },
1673}; 1650};
1674 1651
@@ -1767,10 +1744,10 @@ static void cxt5051_hp_unsol_event(struct hda_codec *codec,
1767 cxt5051_portc_automic(codec); 1744 cxt5051_portc_automic(codec);
1768 break; 1745 break;
1769 } 1746 }
1770 conexant_report_jack(codec, nid); 1747 snd_hda_input_jack_report(codec, nid);
1771} 1748}
1772 1749
1773static struct snd_kcontrol_new cxt5051_playback_mixers[] = { 1750static const struct snd_kcontrol_new cxt5051_playback_mixers[] = {
1774 HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT), 1751 HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT),
1775 { 1752 {
1776 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1753 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -1783,45 +1760,45 @@ static struct snd_kcontrol_new cxt5051_playback_mixers[] = {
1783 {} 1760 {}
1784}; 1761};
1785 1762
1786static struct snd_kcontrol_new cxt5051_capture_mixers[] = { 1763static const struct snd_kcontrol_new cxt5051_capture_mixers[] = {
1787 HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT), 1764 HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT),
1788 HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT), 1765 HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT),
1789 HDA_CODEC_VOLUME("External Mic Volume", 0x14, 0x01, HDA_INPUT), 1766 HDA_CODEC_VOLUME("Mic Volume", 0x14, 0x01, HDA_INPUT),
1790 HDA_CODEC_MUTE("External Mic Switch", 0x14, 0x01, HDA_INPUT), 1767 HDA_CODEC_MUTE("Mic Switch", 0x14, 0x01, HDA_INPUT),
1791 HDA_CODEC_VOLUME("Docking Mic Volume", 0x15, 0x00, HDA_INPUT), 1768 HDA_CODEC_VOLUME("Docking Mic Volume", 0x15, 0x00, HDA_INPUT),
1792 HDA_CODEC_MUTE("Docking Mic Switch", 0x15, 0x00, HDA_INPUT), 1769 HDA_CODEC_MUTE("Docking Mic Switch", 0x15, 0x00, HDA_INPUT),
1793 {} 1770 {}
1794}; 1771};
1795 1772
1796static struct snd_kcontrol_new cxt5051_hp_mixers[] = { 1773static const struct snd_kcontrol_new cxt5051_hp_mixers[] = {
1797 HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT), 1774 HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT),
1798 HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT), 1775 HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT),
1799 HDA_CODEC_VOLUME("External Mic Volume", 0x15, 0x00, HDA_INPUT), 1776 HDA_CODEC_VOLUME("Mic Volume", 0x15, 0x00, HDA_INPUT),
1800 HDA_CODEC_MUTE("External Mic Switch", 0x15, 0x00, HDA_INPUT), 1777 HDA_CODEC_MUTE("Mic Switch", 0x15, 0x00, HDA_INPUT),
1801 {} 1778 {}
1802}; 1779};
1803 1780
1804static struct snd_kcontrol_new cxt5051_hp_dv6736_mixers[] = { 1781static const struct snd_kcontrol_new cxt5051_hp_dv6736_mixers[] = {
1805 HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x00, HDA_INPUT), 1782 HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x00, HDA_INPUT),
1806 HDA_CODEC_MUTE("Capture Switch", 0x14, 0x00, HDA_INPUT), 1783 HDA_CODEC_MUTE("Capture Switch", 0x14, 0x00, HDA_INPUT),
1807 {} 1784 {}
1808}; 1785};
1809 1786
1810static struct snd_kcontrol_new cxt5051_f700_mixers[] = { 1787static const struct snd_kcontrol_new cxt5051_f700_mixers[] = {
1811 HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x01, HDA_INPUT), 1788 HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x01, HDA_INPUT),
1812 HDA_CODEC_MUTE("Capture Switch", 0x14, 0x01, HDA_INPUT), 1789 HDA_CODEC_MUTE("Capture Switch", 0x14, 0x01, HDA_INPUT),
1813 {} 1790 {}
1814}; 1791};
1815 1792
1816static struct snd_kcontrol_new cxt5051_toshiba_mixers[] = { 1793static const struct snd_kcontrol_new cxt5051_toshiba_mixers[] = {
1817 HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT), 1794 HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT),
1818 HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT), 1795 HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT),
1819 HDA_CODEC_VOLUME("External Mic Volume", 0x14, 0x01, HDA_INPUT), 1796 HDA_CODEC_VOLUME("Mic Volume", 0x14, 0x01, HDA_INPUT),
1820 HDA_CODEC_MUTE("External Mic Switch", 0x14, 0x01, HDA_INPUT), 1797 HDA_CODEC_MUTE("Mic Switch", 0x14, 0x01, HDA_INPUT),
1821 {} 1798 {}
1822}; 1799};
1823 1800
1824static struct hda_verb cxt5051_init_verbs[] = { 1801static const struct hda_verb cxt5051_init_verbs[] = {
1825 /* Line in, Mic */ 1802 /* Line in, Mic */
1826 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, 1803 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
1827 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1804 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
@@ -1837,7 +1814,7 @@ static struct hda_verb cxt5051_init_verbs[] = {
1837 {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, 1814 {0x16, AC_VERB_SET_CONNECT_SEL, 0x00},
1838 /* DAC1 */ 1815 /* DAC1 */
1839 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1816 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1840 /* Record selector: Int mic */ 1817 /* Record selector: Internal mic */
1841 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44}, 1818 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44},
1842 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44}, 1819 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44},
1843 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44}, 1820 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44},
@@ -1850,7 +1827,7 @@ static struct hda_verb cxt5051_init_verbs[] = {
1850 { } /* end */ 1827 { } /* end */
1851}; 1828};
1852 1829
1853static struct hda_verb cxt5051_hp_dv6736_init_verbs[] = { 1830static const struct hda_verb cxt5051_hp_dv6736_init_verbs[] = {
1854 /* Line in, Mic */ 1831 /* Line in, Mic */
1855 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, 1832 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
1856 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1833 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
@@ -1864,7 +1841,7 @@ static struct hda_verb cxt5051_hp_dv6736_init_verbs[] = {
1864 {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, 1841 {0x16, AC_VERB_SET_CONNECT_SEL, 0x00},
1865 /* DAC1 */ 1842 /* DAC1 */
1866 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1843 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1867 /* Record selector: Int mic */ 1844 /* Record selector: Internal mic */
1868 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44}, 1845 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44},
1869 {0x14, AC_VERB_SET_CONNECT_SEL, 0x1}, 1846 {0x14, AC_VERB_SET_CONNECT_SEL, 0x1},
1870 /* SPDIF route: PCM */ 1847 /* SPDIF route: PCM */
@@ -1875,7 +1852,7 @@ static struct hda_verb cxt5051_hp_dv6736_init_verbs[] = {
1875 { } /* end */ 1852 { } /* end */
1876}; 1853};
1877 1854
1878static struct hda_verb cxt5051_lenovo_x200_init_verbs[] = { 1855static const struct hda_verb cxt5051_lenovo_x200_init_verbs[] = {
1879 /* Line in, Mic */ 1856 /* Line in, Mic */
1880 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, 1857 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
1881 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1858 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
@@ -1894,7 +1871,7 @@ static struct hda_verb cxt5051_lenovo_x200_init_verbs[] = {
1894 {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, 1871 {0x19, AC_VERB_SET_CONNECT_SEL, 0x00},
1895 /* DAC1 */ 1872 /* DAC1 */
1896 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1873 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1897 /* Record selector: Int mic */ 1874 /* Record selector: Internal mic */
1898 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44}, 1875 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44},
1899 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44}, 1876 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44},
1900 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44}, 1877 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44},
@@ -1908,7 +1885,7 @@ static struct hda_verb cxt5051_lenovo_x200_init_verbs[] = {
1908 { } /* end */ 1885 { } /* end */
1909}; 1886};
1910 1887
1911static struct hda_verb cxt5051_f700_init_verbs[] = { 1888static const struct hda_verb cxt5051_f700_init_verbs[] = {
1912 /* Line in, Mic */ 1889 /* Line in, Mic */
1913 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, 1890 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
1914 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 1891 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
@@ -1922,7 +1899,7 @@ static struct hda_verb cxt5051_f700_init_verbs[] = {
1922 {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, 1899 {0x16, AC_VERB_SET_CONNECT_SEL, 0x00},
1923 /* DAC1 */ 1900 /* DAC1 */
1924 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 1901 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1925 /* Record selector: Int mic */ 1902 /* Record selector: Internal mic */
1926 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44}, 1903 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44},
1927 {0x14, AC_VERB_SET_CONNECT_SEL, 0x1}, 1904 {0x14, AC_VERB_SET_CONNECT_SEL, 0x1},
1928 /* SPDIF route: PCM */ 1905 /* SPDIF route: PCM */
@@ -1939,13 +1916,11 @@ static void cxt5051_init_mic_port(struct hda_codec *codec, hda_nid_t nid,
1939 snd_hda_codec_write(codec, nid, 0, 1916 snd_hda_codec_write(codec, nid, 0,
1940 AC_VERB_SET_UNSOLICITED_ENABLE, 1917 AC_VERB_SET_UNSOLICITED_ENABLE,
1941 AC_USRSP_EN | event); 1918 AC_USRSP_EN | event);
1942#ifdef CONFIG_SND_HDA_INPUT_JACK 1919 snd_hda_input_jack_add(codec, nid, SND_JACK_MICROPHONE, NULL);
1943 conexant_add_jack(codec, nid, SND_JACK_MICROPHONE); 1920 snd_hda_input_jack_report(codec, nid);
1944 conexant_report_jack(codec, nid);
1945#endif
1946} 1921}
1947 1922
1948static struct hda_verb cxt5051_ideapad_init_verbs[] = { 1923static const struct hda_verb cxt5051_ideapad_init_verbs[] = {
1949 /* Subwoofer */ 1924 /* Subwoofer */
1950 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 1925 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1951 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, 1926 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
@@ -1982,10 +1957,11 @@ enum {
1982 CXT5051_F700, /* HP Compaq Presario F700 */ 1957 CXT5051_F700, /* HP Compaq Presario F700 */
1983 CXT5051_TOSHIBA, /* Toshiba M300 & co */ 1958 CXT5051_TOSHIBA, /* Toshiba M300 & co */
1984 CXT5051_IDEAPAD, /* Lenovo IdeaPad Y430 */ 1959 CXT5051_IDEAPAD, /* Lenovo IdeaPad Y430 */
1960 CXT5051_AUTO, /* auto-parser */
1985 CXT5051_MODELS 1961 CXT5051_MODELS
1986}; 1962};
1987 1963
1988static const char *cxt5051_models[CXT5051_MODELS] = { 1964static const char *const cxt5051_models[CXT5051_MODELS] = {
1989 [CXT5051_LAPTOP] = "laptop", 1965 [CXT5051_LAPTOP] = "laptop",
1990 [CXT5051_HP] = "hp", 1966 [CXT5051_HP] = "hp",
1991 [CXT5051_HP_DV6736] = "hp-dv6736", 1967 [CXT5051_HP_DV6736] = "hp-dv6736",
@@ -1993,9 +1969,10 @@ static const char *cxt5051_models[CXT5051_MODELS] = {
1993 [CXT5051_F700] = "hp-700", 1969 [CXT5051_F700] = "hp-700",
1994 [CXT5051_TOSHIBA] = "toshiba", 1970 [CXT5051_TOSHIBA] = "toshiba",
1995 [CXT5051_IDEAPAD] = "ideapad", 1971 [CXT5051_IDEAPAD] = "ideapad",
1972 [CXT5051_AUTO] = "auto",
1996}; 1973};
1997 1974
1998static struct snd_pci_quirk cxt5051_cfg_tbl[] = { 1975static const struct snd_pci_quirk cxt5051_cfg_tbl[] = {
1999 SND_PCI_QUIRK(0x103c, 0x30cf, "HP DV6736", CXT5051_HP_DV6736), 1976 SND_PCI_QUIRK(0x103c, 0x30cf, "HP DV6736", CXT5051_HP_DV6736),
2000 SND_PCI_QUIRK(0x103c, 0x360b, "Compaq Presario CQ60", CXT5051_HP), 1977 SND_PCI_QUIRK(0x103c, 0x360b, "Compaq Presario CQ60", CXT5051_HP),
2001 SND_PCI_QUIRK(0x103c, 0x30ea, "Compaq Presario F700", CXT5051_F700), 1978 SND_PCI_QUIRK(0x103c, 0x30ea, "Compaq Presario F700", CXT5051_F700),
@@ -2013,6 +1990,16 @@ static int patch_cxt5051(struct hda_codec *codec)
2013 struct conexant_spec *spec; 1990 struct conexant_spec *spec;
2014 int board_config; 1991 int board_config;
2015 1992
1993 board_config = snd_hda_check_board_config(codec, CXT5051_MODELS,
1994 cxt5051_models,
1995 cxt5051_cfg_tbl);
1996#if 0 /* use the old method just for safety */
1997 if (board_config < 0)
1998 board_config = CXT5051_AUTO;
1999#endif
2000 if (board_config == CXT5051_AUTO)
2001 return patch_conexant_auto(codec);
2002
2016 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 2003 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2017 if (!spec) 2004 if (!spec)
2018 return -ENOMEM; 2005 return -ENOMEM;
@@ -2043,9 +2030,6 @@ static int patch_cxt5051(struct hda_codec *codec)
2043 2030
2044 codec->patch_ops.unsol_event = cxt5051_hp_unsol_event; 2031 codec->patch_ops.unsol_event = cxt5051_hp_unsol_event;
2045 2032
2046 board_config = snd_hda_check_board_config(codec, CXT5051_MODELS,
2047 cxt5051_models,
2048 cxt5051_cfg_tbl);
2049 spec->auto_mic = AUTO_MIC_PORTB | AUTO_MIC_PORTC; 2033 spec->auto_mic = AUTO_MIC_PORTB | AUTO_MIC_PORTC;
2050 switch (board_config) { 2034 switch (board_config) {
2051 case CXT5051_HP: 2035 case CXT5051_HP:
@@ -2087,39 +2071,49 @@ static int patch_cxt5051(struct hda_codec *codec)
2087 2071
2088/* Conexant 5066 specific */ 2072/* Conexant 5066 specific */
2089 2073
2090static hda_nid_t cxt5066_dac_nids[1] = { 0x10 }; 2074static const hda_nid_t cxt5066_dac_nids[1] = { 0x10 };
2091static hda_nid_t cxt5066_adc_nids[3] = { 0x14, 0x15, 0x16 }; 2075static const hda_nid_t cxt5066_adc_nids[3] = { 0x14, 0x15, 0x16 };
2092static hda_nid_t cxt5066_capsrc_nids[1] = { 0x17 }; 2076static const hda_nid_t cxt5066_capsrc_nids[1] = { 0x17 };
2093#define CXT5066_SPDIF_OUT 0x21 2077static const hda_nid_t cxt5066_digout_pin_nids[2] = { 0x20, 0x22 };
2094 2078
2095/* OLPC's microphone port is DC coupled for use with external sensors, 2079/* OLPC's microphone port is DC coupled for use with external sensors,
2096 * therefore we use a 50% mic bias in order to center the input signal with 2080 * therefore we use a 50% mic bias in order to center the input signal with
2097 * the DC input range of the codec. */ 2081 * the DC input range of the codec. */
2098#define CXT5066_OLPC_EXT_MIC_BIAS PIN_VREF50 2082#define CXT5066_OLPC_EXT_MIC_BIAS PIN_VREF50
2099 2083
2100static struct hda_channel_mode cxt5066_modes[1] = { 2084static const struct hda_channel_mode cxt5066_modes[1] = {
2101 { 2, NULL }, 2085 { 2, NULL },
2102}; 2086};
2103 2087
2088#define HP_PRESENT_PORT_A (1 << 0)
2089#define HP_PRESENT_PORT_D (1 << 1)
2090#define hp_port_a_present(spec) ((spec)->hp_present & HP_PRESENT_PORT_A)
2091#define hp_port_d_present(spec) ((spec)->hp_present & HP_PRESENT_PORT_D)
2092
2104static void cxt5066_update_speaker(struct hda_codec *codec) 2093static void cxt5066_update_speaker(struct hda_codec *codec)
2105{ 2094{
2106 struct conexant_spec *spec = codec->spec; 2095 struct conexant_spec *spec = codec->spec;
2107 unsigned int pinctl; 2096 unsigned int pinctl;
2108 2097
2109 snd_printdd("CXT5066: update speaker, hp_present=%d\n", 2098 snd_printdd("CXT5066: update speaker, hp_present=%d, cur_eapd=%d\n",
2110 spec->hp_present); 2099 spec->hp_present, spec->cur_eapd);
2111 2100
2112 /* Port A (HP) */ 2101 /* Port A (HP) */
2113 pinctl = ((spec->hp_present & 1) && spec->cur_eapd) ? PIN_HP : 0; 2102 pinctl = (hp_port_a_present(spec) && spec->cur_eapd) ? PIN_HP : 0;
2114 snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 2103 snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
2115 pinctl); 2104 pinctl);
2116 2105
2117 /* Port D (HP/LO) */ 2106 /* Port D (HP/LO) */
2118 pinctl = ((spec->hp_present & 2) && spec->cur_eapd) 2107 pinctl = spec->cur_eapd ? spec->port_d_mode : 0;
2119 ? spec->port_d_mode : 0; 2108 if (spec->dell_automute || spec->thinkpad) {
2120 /* Mute if Port A is connected on Thinkpad */ 2109 /* Mute if Port A is connected */
2121 if (spec->thinkpad && (spec->hp_present & 1)) 2110 if (hp_port_a_present(spec))
2122 pinctl = 0; 2111 pinctl = 0;
2112 } else {
2113 /* Thinkpad/Dell doesn't give pin-D status */
2114 if (!hp_port_d_present(spec))
2115 pinctl = 0;
2116 }
2123 snd_hda_codec_write(codec, 0x1c, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 2117 snd_hda_codec_write(codec, 0x1c, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
2124 pinctl); 2118 pinctl);
2125 2119
@@ -2127,14 +2121,6 @@ static void cxt5066_update_speaker(struct hda_codec *codec)
2127 pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0; 2121 pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0;
2128 snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 2122 snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
2129 pinctl); 2123 pinctl);
2130
2131 if (spec->dell_automute) {
2132 /* DELL AIO Port Rule: PortA > PortD > IntSpk */
2133 pinctl = (!(spec->hp_present & 1) && spec->cur_eapd)
2134 ? PIN_OUT : 0;
2135 snd_hda_codec_write(codec, 0x1c, 0,
2136 AC_VERB_SET_PIN_WIDGET_CONTROL, pinctl);
2137 }
2138} 2124}
2139 2125
2140/* turn on/off EAPD (+ mute HP) as a master switch */ 2126/* turn on/off EAPD (+ mute HP) as a master switch */
@@ -2250,7 +2236,7 @@ static void cxt5066_vostro_automic(struct hda_codec *codec)
2250 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2236 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2251 {} 2237 {}
2252 }; 2238 };
2253 static struct hda_verb ext_mic_absent[] = { 2239 static const struct hda_verb ext_mic_absent[] = {
2254 /* enable internal mic, port C */ 2240 /* enable internal mic, port C */
2255 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 2241 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2256 2242
@@ -2283,7 +2269,7 @@ static void cxt5066_ideapad_automic(struct hda_codec *codec)
2283 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2269 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2284 {} 2270 {}
2285 }; 2271 };
2286 static struct hda_verb ext_mic_absent[] = { 2272 static const struct hda_verb ext_mic_absent[] = {
2287 {0x14, AC_VERB_SET_CONNECT_SEL, 2}, 2273 {0x14, AC_VERB_SET_CONNECT_SEL, 2},
2288 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 2274 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2289 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2275 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
@@ -2300,6 +2286,19 @@ static void cxt5066_ideapad_automic(struct hda_codec *codec)
2300 } 2286 }
2301} 2287}
2302 2288
2289
2290/* toggle input of built-in digital mic and mic jack appropriately */
2291static void cxt5066_asus_automic(struct hda_codec *codec)
2292{
2293 unsigned int present;
2294
2295 present = snd_hda_jack_detect(codec, 0x1b);
2296 snd_printdd("CXT5066: external microphone present=%d\n", present);
2297 snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_CONNECT_SEL,
2298 present ? 1 : 0);
2299}
2300
2301
2303/* toggle input of built-in digital mic and mic jack appropriately */ 2302/* toggle input of built-in digital mic and mic jack appropriately */
2304static void cxt5066_hp_laptop_automic(struct hda_codec *codec) 2303static void cxt5066_hp_laptop_automic(struct hda_codec *codec)
2305{ 2304{
@@ -2318,7 +2317,7 @@ static void cxt5066_thinkpad_automic(struct hda_codec *codec)
2318{ 2317{
2319 unsigned int ext_present, dock_present; 2318 unsigned int ext_present, dock_present;
2320 2319
2321 static struct hda_verb ext_mic_present[] = { 2320 static const struct hda_verb ext_mic_present[] = {
2322 {0x14, AC_VERB_SET_CONNECT_SEL, 0}, 2321 {0x14, AC_VERB_SET_CONNECT_SEL, 0},
2323 {0x17, AC_VERB_SET_CONNECT_SEL, 1}, 2322 {0x17, AC_VERB_SET_CONNECT_SEL, 1},
2324 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 2323 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
@@ -2326,7 +2325,7 @@ static void cxt5066_thinkpad_automic(struct hda_codec *codec)
2326 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2325 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2327 {} 2326 {}
2328 }; 2327 };
2329 static struct hda_verb dock_mic_present[] = { 2328 static const struct hda_verb dock_mic_present[] = {
2330 {0x14, AC_VERB_SET_CONNECT_SEL, 0}, 2329 {0x14, AC_VERB_SET_CONNECT_SEL, 0},
2331 {0x17, AC_VERB_SET_CONNECT_SEL, 0}, 2330 {0x17, AC_VERB_SET_CONNECT_SEL, 0},
2332 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, 2331 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
@@ -2334,7 +2333,7 @@ static void cxt5066_thinkpad_automic(struct hda_codec *codec)
2334 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2333 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2335 {} 2334 {}
2336 }; 2335 };
2337 static struct hda_verb ext_mic_absent[] = { 2336 static const struct hda_verb ext_mic_absent[] = {
2338 {0x14, AC_VERB_SET_CONNECT_SEL, 2}, 2337 {0x14, AC_VERB_SET_CONNECT_SEL, 2},
2339 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 2338 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2340 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2339 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
@@ -2368,86 +2367,62 @@ static void cxt5066_hp_automute(struct hda_codec *codec)
2368 /* Port D */ 2367 /* Port D */
2369 portD = snd_hda_jack_detect(codec, 0x1c); 2368 portD = snd_hda_jack_detect(codec, 0x1c);
2370 2369
2371 spec->hp_present = !!(portA); 2370 spec->hp_present = portA ? HP_PRESENT_PORT_A : 0;
2372 spec->hp_present |= portD ? 2 : 0; 2371 spec->hp_present |= portD ? HP_PRESENT_PORT_D : 0;
2373 snd_printdd("CXT5066: hp automute portA=%x portD=%x present=%d\n", 2372 snd_printdd("CXT5066: hp automute portA=%x portD=%x present=%d\n",
2374 portA, portD, spec->hp_present); 2373 portA, portD, spec->hp_present);
2375 cxt5066_update_speaker(codec); 2374 cxt5066_update_speaker(codec);
2376} 2375}
2377 2376
2378/* unsolicited event for jack sensing */ 2377/* Dispatch the right mic autoswitch function */
2379static void cxt5066_olpc_unsol_event(struct hda_codec *codec, unsigned int res) 2378static void cxt5066_automic(struct hda_codec *codec)
2380{ 2379{
2381 struct conexant_spec *spec = codec->spec; 2380 struct conexant_spec *spec = codec->spec;
2382 snd_printdd("CXT5066: unsol event %x (%x)\n", res, res >> 26);
2383 switch (res >> 26) {
2384 case CONEXANT_HP_EVENT:
2385 cxt5066_hp_automute(codec);
2386 break;
2387 case CONEXANT_MIC_EVENT:
2388 /* ignore mic events in DC mode; we're always using the jack */
2389 if (!spec->dc_enable)
2390 cxt5066_olpc_automic(codec);
2391 break;
2392 }
2393}
2394 2381
2395/* unsolicited event for jack sensing */ 2382 if (spec->dell_vostro)
2396static void cxt5066_vostro_event(struct hda_codec *codec, unsigned int res)
2397{
2398 snd_printdd("CXT5066_vostro: unsol event %x (%x)\n", res, res >> 26);
2399 switch (res >> 26) {
2400 case CONEXANT_HP_EVENT:
2401 cxt5066_hp_automute(codec);
2402 break;
2403 case CONEXANT_MIC_EVENT:
2404 cxt5066_vostro_automic(codec); 2383 cxt5066_vostro_automic(codec);
2405 break; 2384 else if (spec->ideapad)
2406 }
2407}
2408
2409/* unsolicited event for jack sensing */
2410static void cxt5066_ideapad_event(struct hda_codec *codec, unsigned int res)
2411{
2412 snd_printdd("CXT5066_ideapad: unsol event %x (%x)\n", res, res >> 26);
2413 switch (res >> 26) {
2414 case CONEXANT_HP_EVENT:
2415 cxt5066_hp_automute(codec);
2416 break;
2417 case CONEXANT_MIC_EVENT:
2418 cxt5066_ideapad_automic(codec); 2385 cxt5066_ideapad_automic(codec);
2419 break; 2386 else if (spec->thinkpad)
2420 } 2387 cxt5066_thinkpad_automic(codec);
2388 else if (spec->hp_laptop)
2389 cxt5066_hp_laptop_automic(codec);
2390 else if (spec->asus)
2391 cxt5066_asus_automic(codec);
2421} 2392}
2422 2393
2423/* unsolicited event for jack sensing */ 2394/* unsolicited event for jack sensing */
2424static void cxt5066_hp_laptop_event(struct hda_codec *codec, unsigned int res) 2395static void cxt5066_olpc_unsol_event(struct hda_codec *codec, unsigned int res)
2425{ 2396{
2426 snd_printdd("CXT5066_hp_laptop: unsol event %x (%x)\n", res, res >> 26); 2397 struct conexant_spec *spec = codec->spec;
2398 snd_printdd("CXT5066: unsol event %x (%x)\n", res, res >> 26);
2427 switch (res >> 26) { 2399 switch (res >> 26) {
2428 case CONEXANT_HP_EVENT: 2400 case CONEXANT_HP_EVENT:
2429 cxt5066_hp_automute(codec); 2401 cxt5066_hp_automute(codec);
2430 break; 2402 break;
2431 case CONEXANT_MIC_EVENT: 2403 case CONEXANT_MIC_EVENT:
2432 cxt5066_hp_laptop_automic(codec); 2404 /* ignore mic events in DC mode; we're always using the jack */
2405 if (!spec->dc_enable)
2406 cxt5066_olpc_automic(codec);
2433 break; 2407 break;
2434 } 2408 }
2435} 2409}
2436 2410
2437/* unsolicited event for jack sensing */ 2411/* unsolicited event for jack sensing */
2438static void cxt5066_thinkpad_event(struct hda_codec *codec, unsigned int res) 2412static void cxt5066_unsol_event(struct hda_codec *codec, unsigned int res)
2439{ 2413{
2440 snd_printdd("CXT5066_thinkpad: unsol event %x (%x)\n", res, res >> 26); 2414 snd_printdd("CXT5066: unsol event %x (%x)\n", res, res >> 26);
2441 switch (res >> 26) { 2415 switch (res >> 26) {
2442 case CONEXANT_HP_EVENT: 2416 case CONEXANT_HP_EVENT:
2443 cxt5066_hp_automute(codec); 2417 cxt5066_hp_automute(codec);
2444 break; 2418 break;
2445 case CONEXANT_MIC_EVENT: 2419 case CONEXANT_MIC_EVENT:
2446 cxt5066_thinkpad_automic(codec); 2420 cxt5066_automic(codec);
2447 break; 2421 break;
2448 } 2422 }
2449} 2423}
2450 2424
2425
2451static const struct hda_input_mux cxt5066_analog_mic_boost = { 2426static const struct hda_input_mux cxt5066_analog_mic_boost = {
2452 .num_items = 5, 2427 .num_items = 5,
2453 .items = { 2428 .items = {
@@ -2621,7 +2596,28 @@ static void cxt5066_olpc_capture_cleanup(struct hda_codec *codec)
2621 spec->recording = 0; 2596 spec->recording = 0;
2622} 2597}
2623 2598
2624static struct hda_input_mux cxt5066_capture_source = { 2599static void conexant_check_dig_outs(struct hda_codec *codec,
2600 const hda_nid_t *dig_pins,
2601 int num_pins)
2602{
2603 struct conexant_spec *spec = codec->spec;
2604 hda_nid_t *nid_loc = &spec->multiout.dig_out_nid;
2605 int i;
2606
2607 for (i = 0; i < num_pins; i++, dig_pins++) {
2608 unsigned int cfg = snd_hda_codec_get_pincfg(codec, *dig_pins);
2609 if (get_defcfg_connect(cfg) == AC_JACK_PORT_NONE)
2610 continue;
2611 if (snd_hda_get_connections(codec, *dig_pins, nid_loc, 1) != 1)
2612 continue;
2613 if (spec->slave_dig_outs[0])
2614 nid_loc++;
2615 else
2616 nid_loc = spec->slave_dig_outs;
2617 }
2618}
2619
2620static const struct hda_input_mux cxt5066_capture_source = {
2625 .num_items = 4, 2621 .num_items = 4,
2626 .items = { 2622 .items = {
2627 { "Mic B", 0 }, 2623 { "Mic B", 0 },
@@ -2631,7 +2627,7 @@ static struct hda_input_mux cxt5066_capture_source = {
2631 }, 2627 },
2632}; 2628};
2633 2629
2634static struct hda_bind_ctls cxt5066_bind_capture_vol_others = { 2630static const struct hda_bind_ctls cxt5066_bind_capture_vol_others = {
2635 .ops = &snd_hda_bind_vol, 2631 .ops = &snd_hda_bind_vol,
2636 .values = { 2632 .values = {
2637 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_INPUT), 2633 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_INPUT),
@@ -2640,7 +2636,7 @@ static struct hda_bind_ctls cxt5066_bind_capture_vol_others = {
2640 }, 2636 },
2641}; 2637};
2642 2638
2643static struct hda_bind_ctls cxt5066_bind_capture_sw_others = { 2639static const struct hda_bind_ctls cxt5066_bind_capture_sw_others = {
2644 .ops = &snd_hda_bind_sw, 2640 .ops = &snd_hda_bind_sw,
2645 .values = { 2641 .values = {
2646 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_INPUT), 2642 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_INPUT),
@@ -2649,12 +2645,12 @@ static struct hda_bind_ctls cxt5066_bind_capture_sw_others = {
2649 }, 2645 },
2650}; 2646};
2651 2647
2652static struct snd_kcontrol_new cxt5066_mixer_master[] = { 2648static const struct snd_kcontrol_new cxt5066_mixer_master[] = {
2653 HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT), 2649 HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT),
2654 {} 2650 {}
2655}; 2651};
2656 2652
2657static struct snd_kcontrol_new cxt5066_mixer_master_olpc[] = { 2653static const struct snd_kcontrol_new cxt5066_mixer_master_olpc[] = {
2658 { 2654 {
2659 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2655 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2660 .name = "Master Playback Volume", 2656 .name = "Master Playback Volume",
@@ -2673,7 +2669,7 @@ static struct snd_kcontrol_new cxt5066_mixer_master_olpc[] = {
2673 {} 2669 {}
2674}; 2670};
2675 2671
2676static struct snd_kcontrol_new cxt5066_mixer_olpc_dc[] = { 2672static const struct snd_kcontrol_new cxt5066_mixer_olpc_dc[] = {
2677 { 2673 {
2678 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2674 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2679 .name = "DC Mode Enable Switch", 2675 .name = "DC Mode Enable Switch",
@@ -2691,7 +2687,7 @@ static struct snd_kcontrol_new cxt5066_mixer_olpc_dc[] = {
2691 {} 2687 {}
2692}; 2688};
2693 2689
2694static struct snd_kcontrol_new cxt5066_mixers[] = { 2690static const struct snd_kcontrol_new cxt5066_mixers[] = {
2695 { 2691 {
2696 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2692 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2697 .name = "Master Playback Switch", 2693 .name = "Master Playback Switch",
@@ -2714,10 +2710,10 @@ static struct snd_kcontrol_new cxt5066_mixers[] = {
2714 {} 2710 {}
2715}; 2711};
2716 2712
2717static struct snd_kcontrol_new cxt5066_vostro_mixers[] = { 2713static const struct snd_kcontrol_new cxt5066_vostro_mixers[] = {
2718 { 2714 {
2719 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2715 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2720 .name = "Int Mic Boost Capture Enum", 2716 .name = "Internal Mic Boost Capture Enum",
2721 .info = cxt5066_mic_boost_mux_enum_info, 2717 .info = cxt5066_mic_boost_mux_enum_info,
2722 .get = cxt5066_mic_boost_mux_enum_get, 2718 .get = cxt5066_mic_boost_mux_enum_get,
2723 .put = cxt5066_mic_boost_mux_enum_put, 2719 .put = cxt5066_mic_boost_mux_enum_put,
@@ -2726,7 +2722,7 @@ static struct snd_kcontrol_new cxt5066_vostro_mixers[] = {
2726 {} 2722 {}
2727}; 2723};
2728 2724
2729static struct hda_verb cxt5066_init_verbs[] = { 2725static const struct hda_verb cxt5066_init_verbs[] = {
2730 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port B */ 2726 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port B */
2731 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port C */ 2727 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port C */
2732 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port F */ 2728 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port F */
@@ -2781,7 +2777,7 @@ static struct hda_verb cxt5066_init_verbs[] = {
2781 { } /* end */ 2777 { } /* end */
2782}; 2778};
2783 2779
2784static struct hda_verb cxt5066_init_verbs_olpc[] = { 2780static const struct hda_verb cxt5066_init_verbs_olpc[] = {
2785 /* Port A: headphones */ 2781 /* Port A: headphones */
2786 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, 2782 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2787 {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ 2783 {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
@@ -2842,7 +2838,7 @@ static struct hda_verb cxt5066_init_verbs_olpc[] = {
2842 { } /* end */ 2838 { } /* end */
2843}; 2839};
2844 2840
2845static struct hda_verb cxt5066_init_verbs_vostro[] = { 2841static const struct hda_verb cxt5066_init_verbs_vostro[] = {
2846 /* Port A: headphones */ 2842 /* Port A: headphones */
2847 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 2843 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2848 {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ 2844 {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
@@ -2903,7 +2899,7 @@ static struct hda_verb cxt5066_init_verbs_vostro[] = {
2903 { } /* end */ 2899 { } /* end */
2904}; 2900};
2905 2901
2906static struct hda_verb cxt5066_init_verbs_ideapad[] = { 2902static const struct hda_verb cxt5066_init_verbs_ideapad[] = {
2907 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port B */ 2903 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port B */
2908 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port C */ 2904 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port C */
2909 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port F */ 2905 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port F */
@@ -2943,7 +2939,7 @@ static struct hda_verb cxt5066_init_verbs_ideapad[] = {
2943 {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2939 {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2944 2940
2945 /* internal microphone */ 2941 /* internal microphone */
2946 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* enable int mic */ 2942 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* enable internal mic */
2947 2943
2948 /* EAPD */ 2944 /* EAPD */
2949 {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ 2945 {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
@@ -2953,7 +2949,7 @@ static struct hda_verb cxt5066_init_verbs_ideapad[] = {
2953 { } /* end */ 2949 { } /* end */
2954}; 2950};
2955 2951
2956static struct hda_verb cxt5066_init_verbs_thinkpad[] = { 2952static const struct hda_verb cxt5066_init_verbs_thinkpad[] = {
2957 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port F */ 2953 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port F */
2958 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port E */ 2954 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port E */
2959 2955
@@ -2998,7 +2994,7 @@ static struct hda_verb cxt5066_init_verbs_thinkpad[] = {
2998 {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2994 {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2999 2995
3000 /* internal microphone */ 2996 /* internal microphone */
3001 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* enable int mic */ 2997 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* enable internal mic */
3002 2998
3003 /* EAPD */ 2999 /* EAPD */
3004 {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ 3000 {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
@@ -3011,13 +3007,13 @@ static struct hda_verb cxt5066_init_verbs_thinkpad[] = {
3011 { } /* end */ 3007 { } /* end */
3012}; 3008};
3013 3009
3014static struct hda_verb cxt5066_init_verbs_portd_lo[] = { 3010static const struct hda_verb cxt5066_init_verbs_portd_lo[] = {
3015 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 3011 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
3016 { } /* end */ 3012 { } /* end */
3017}; 3013};
3018 3014
3019 3015
3020static struct hda_verb cxt5066_init_verbs_hp_laptop[] = { 3016static const struct hda_verb cxt5066_init_verbs_hp_laptop[] = {
3021 {0x14, AC_VERB_SET_CONNECT_SEL, 0x0}, 3017 {0x14, AC_VERB_SET_CONNECT_SEL, 0x0},
3022 {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, 3018 {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
3023 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, 3019 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
@@ -3027,20 +3023,11 @@ static struct hda_verb cxt5066_init_verbs_hp_laptop[] = {
3027/* initialize jack-sensing, too */ 3023/* initialize jack-sensing, too */
3028static int cxt5066_init(struct hda_codec *codec) 3024static int cxt5066_init(struct hda_codec *codec)
3029{ 3025{
3030 struct conexant_spec *spec = codec->spec;
3031
3032 snd_printdd("CXT5066: init\n"); 3026 snd_printdd("CXT5066: init\n");
3033 conexant_init(codec); 3027 conexant_init(codec);
3034 if (codec->patch_ops.unsol_event) { 3028 if (codec->patch_ops.unsol_event) {
3035 cxt5066_hp_automute(codec); 3029 cxt5066_hp_automute(codec);
3036 if (spec->dell_vostro) 3030 cxt5066_automic(codec);
3037 cxt5066_vostro_automic(codec);
3038 else if (spec->ideapad)
3039 cxt5066_ideapad_automic(codec);
3040 else if (spec->thinkpad)
3041 cxt5066_thinkpad_automic(codec);
3042 else if (spec->hp_laptop)
3043 cxt5066_hp_laptop_automic(codec);
3044 } 3031 }
3045 cxt5066_set_mic_boost(codec); 3032 cxt5066_set_mic_boost(codec);
3046 return 0; 3033 return 0;
@@ -3065,45 +3052,58 @@ enum {
3065 CXT5066_LAPTOP, /* Laptops w/ EAPD support */ 3052 CXT5066_LAPTOP, /* Laptops w/ EAPD support */
3066 CXT5066_DELL_LAPTOP, /* Dell Laptop */ 3053 CXT5066_DELL_LAPTOP, /* Dell Laptop */
3067 CXT5066_OLPC_XO_1_5, /* OLPC XO 1.5 */ 3054 CXT5066_OLPC_XO_1_5, /* OLPC XO 1.5 */
3068 CXT5066_DELL_VOSTO, /* Dell Vostro 1015i */ 3055 CXT5066_DELL_VOSTRO, /* Dell Vostro 1015i */
3069 CXT5066_IDEAPAD, /* Lenovo IdeaPad U150 */ 3056 CXT5066_IDEAPAD, /* Lenovo IdeaPad U150 */
3070 CXT5066_THINKPAD, /* Lenovo ThinkPad T410s, others? */ 3057 CXT5066_THINKPAD, /* Lenovo ThinkPad T410s, others? */
3058 CXT5066_ASUS, /* Asus K52JU, Lenovo G560 - Int mic at 0x1a and Ext mic at 0x1b */
3071 CXT5066_HP_LAPTOP, /* HP Laptop */ 3059 CXT5066_HP_LAPTOP, /* HP Laptop */
3060 CXT5066_AUTO, /* BIOS auto-parser */
3072 CXT5066_MODELS 3061 CXT5066_MODELS
3073}; 3062};
3074 3063
3075static const char *cxt5066_models[CXT5066_MODELS] = { 3064static const char * const cxt5066_models[CXT5066_MODELS] = {
3076 [CXT5066_LAPTOP] = "laptop", 3065 [CXT5066_LAPTOP] = "laptop",
3077 [CXT5066_DELL_LAPTOP] = "dell-laptop", 3066 [CXT5066_DELL_LAPTOP] = "dell-laptop",
3078 [CXT5066_OLPC_XO_1_5] = "olpc-xo-1_5", 3067 [CXT5066_OLPC_XO_1_5] = "olpc-xo-1_5",
3079 [CXT5066_DELL_VOSTO] = "dell-vostro", 3068 [CXT5066_DELL_VOSTRO] = "dell-vostro",
3080 [CXT5066_IDEAPAD] = "ideapad", 3069 [CXT5066_IDEAPAD] = "ideapad",
3081 [CXT5066_THINKPAD] = "thinkpad", 3070 [CXT5066_THINKPAD] = "thinkpad",
3071 [CXT5066_ASUS] = "asus",
3082 [CXT5066_HP_LAPTOP] = "hp-laptop", 3072 [CXT5066_HP_LAPTOP] = "hp-laptop",
3073 [CXT5066_AUTO] = "auto",
3083}; 3074};
3084 3075
3085static struct snd_pci_quirk cxt5066_cfg_tbl[] = { 3076static const struct snd_pci_quirk cxt5066_cfg_tbl[] = {
3086 SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board", 3077 SND_PCI_QUIRK(0x1025, 0x054c, "Acer Aspire 3830TG", CXT5066_AUTO),
3087 CXT5066_LAPTOP), 3078 SND_PCI_QUIRK_MASK(0x1025, 0xff00, 0x0400, "Acer", CXT5066_IDEAPAD),
3088 SND_PCI_QUIRK(0x1028, 0x02f5, "Dell", 3079 SND_PCI_QUIRK(0x1028, 0x02d8, "Dell Vostro", CXT5066_DELL_VOSTRO),
3089 CXT5066_DELL_LAPTOP), 3080 SND_PCI_QUIRK(0x1028, 0x02f5, "Dell Vostro 320", CXT5066_IDEAPAD),
3090 SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5), 3081 SND_PCI_QUIRK(0x1028, 0x0401, "Dell Vostro 1014", CXT5066_DELL_VOSTRO),
3091 SND_PCI_QUIRK(0x1028, 0x02d8, "Dell Vostro", CXT5066_DELL_VOSTO), 3082 SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTRO),
3092 SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTO),
3093 SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD), 3083 SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD),
3084 SND_PCI_QUIRK(0x1028, 0x050f, "Dell Inspiron", CXT5066_IDEAPAD),
3085 SND_PCI_QUIRK(0x1028, 0x0510, "Dell Vostro", CXT5066_IDEAPAD),
3094 SND_PCI_QUIRK(0x103c, 0x360b, "HP G60", CXT5066_HP_LAPTOP), 3086 SND_PCI_QUIRK(0x103c, 0x360b, "HP G60", CXT5066_HP_LAPTOP),
3087 SND_PCI_QUIRK(0x1043, 0x13f3, "Asus A52J", CXT5066_ASUS),
3088 SND_PCI_QUIRK(0x1043, 0x1643, "Asus K52JU", CXT5066_ASUS),
3089 SND_PCI_QUIRK(0x1043, 0x1993, "Asus U50F", CXT5066_ASUS),
3095 SND_PCI_QUIRK(0x1179, 0xff1e, "Toshiba Satellite C650D", CXT5066_IDEAPAD), 3090 SND_PCI_QUIRK(0x1179, 0xff1e, "Toshiba Satellite C650D", CXT5066_IDEAPAD),
3096 SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba Satellite P500-PSPGSC-01800T", CXT5066_OLPC_XO_1_5), 3091 SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba Satellite P500-PSPGSC-01800T", CXT5066_OLPC_XO_1_5),
3097 SND_PCI_QUIRK(0x1179, 0xffe0, "Toshiba Satellite Pro T130-15F", CXT5066_OLPC_XO_1_5), 3092 SND_PCI_QUIRK(0x1179, 0xffe0, "Toshiba Satellite Pro T130-15F", CXT5066_OLPC_XO_1_5),
3093 SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board",
3094 CXT5066_LAPTOP),
3095 SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5),
3098 SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD), 3096 SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD),
3099 SND_PCI_QUIRK(0x17aa, 0x21b2, "Thinkpad X100e", CXT5066_IDEAPAD), 3097 SND_PCI_QUIRK(0x17aa, 0x21c5, "Thinkpad Edge 13", CXT5066_THINKPAD),
3100 SND_PCI_QUIRK(0x17aa, 0x21b3, "Thinkpad Edge 13 (197)", CXT5066_IDEAPAD), 3098 SND_PCI_QUIRK(0x17aa, 0x21c6, "Thinkpad Edge 13", CXT5066_ASUS),
3101 SND_PCI_QUIRK(0x17aa, 0x21b4, "Thinkpad Edge", CXT5066_IDEAPAD),
3102 SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo Thinkpad", CXT5066_THINKPAD), 3099 SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo Thinkpad", CXT5066_THINKPAD),
3103 SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G series", CXT5066_IDEAPAD), 3100 SND_PCI_QUIRK(0x17aa, 0x21da, "Lenovo X220", CXT5066_THINKPAD),
3104 SND_PCI_QUIRK(0x17aa, 0x390a, "Lenovo S10-3t", CXT5066_IDEAPAD), 3101 SND_PCI_QUIRK(0x17aa, 0x21db, "Lenovo X220-tablet", CXT5066_THINKPAD),
3105 SND_PCI_QUIRK(0x17aa, 0x3938, "Lenovo G series (AMD)", CXT5066_IDEAPAD), 3102 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo U350", CXT5066_ASUS),
3106 SND_PCI_QUIRK(0x17aa, 0x3a0d, "ideapad", CXT5066_IDEAPAD), 3103 SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G560", CXT5066_ASUS),
3104 SND_PCI_QUIRK(0x17aa, 0x3938, "Lenovo G565", CXT5066_AUTO),
3105 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", CXT5066_IDEAPAD), /* Fallback for Lenovos without dock mic */
3106 SND_PCI_QUIRK(0x1b0a, 0x2092, "CyberpowerPC Gamer Xplorer N57001", CXT5066_AUTO),
3107 {} 3107 {}
3108}; 3108};
3109 3109
@@ -3112,6 +3112,15 @@ static int patch_cxt5066(struct hda_codec *codec)
3112 struct conexant_spec *spec; 3112 struct conexant_spec *spec;
3113 int board_config; 3113 int board_config;
3114 3114
3115 board_config = snd_hda_check_board_config(codec, CXT5066_MODELS,
3116 cxt5066_models, cxt5066_cfg_tbl);
3117#if 0 /* use the old method just for safety */
3118 if (board_config < 0)
3119 board_config = CXT5066_AUTO;
3120#endif
3121 if (board_config == CXT5066_AUTO)
3122 return patch_conexant_auto(codec);
3123
3115 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 3124 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3116 if (!spec) 3125 if (!spec)
3117 return -ENOMEM; 3126 return -ENOMEM;
@@ -3124,7 +3133,8 @@ static int patch_cxt5066(struct hda_codec *codec)
3124 spec->multiout.max_channels = 2; 3133 spec->multiout.max_channels = 2;
3125 spec->multiout.num_dacs = ARRAY_SIZE(cxt5066_dac_nids); 3134 spec->multiout.num_dacs = ARRAY_SIZE(cxt5066_dac_nids);
3126 spec->multiout.dac_nids = cxt5066_dac_nids; 3135 spec->multiout.dac_nids = cxt5066_dac_nids;
3127 spec->multiout.dig_out_nid = CXT5066_SPDIF_OUT; 3136 conexant_check_dig_outs(codec, cxt5066_digout_pin_nids,
3137 ARRAY_SIZE(cxt5066_digout_pin_nids));
3128 spec->num_adc_nids = 1; 3138 spec->num_adc_nids = 1;
3129 spec->adc_nids = cxt5066_adc_nids; 3139 spec->adc_nids = cxt5066_adc_nids;
3130 spec->capsrc_nids = cxt5066_capsrc_nids; 3140 spec->capsrc_nids = cxt5066_capsrc_nids;
@@ -3141,8 +3151,6 @@ static int patch_cxt5066(struct hda_codec *codec)
3141 3151
3142 set_beep_amp(spec, 0x13, 0, HDA_OUTPUT); 3152 set_beep_amp(spec, 0x13, 0, HDA_OUTPUT);
3143 3153
3144 board_config = snd_hda_check_board_config(codec, CXT5066_MODELS,
3145 cxt5066_models, cxt5066_cfg_tbl);
3146 switch (board_config) { 3154 switch (board_config) {
3147 default: 3155 default:
3148 case CXT5066_LAPTOP: 3156 case CXT5066_LAPTOP:
@@ -3158,17 +3166,20 @@ static int patch_cxt5066(struct hda_codec *codec)
3158 spec->num_init_verbs++; 3166 spec->num_init_verbs++;
3159 spec->dell_automute = 1; 3167 spec->dell_automute = 1;
3160 break; 3168 break;
3169 case CXT5066_ASUS:
3161 case CXT5066_HP_LAPTOP: 3170 case CXT5066_HP_LAPTOP:
3162 codec->patch_ops.init = cxt5066_init; 3171 codec->patch_ops.init = cxt5066_init;
3163 codec->patch_ops.unsol_event = cxt5066_hp_laptop_event; 3172 codec->patch_ops.unsol_event = cxt5066_unsol_event;
3164 spec->init_verbs[spec->num_init_verbs] = 3173 spec->init_verbs[spec->num_init_verbs] =
3165 cxt5066_init_verbs_hp_laptop; 3174 cxt5066_init_verbs_hp_laptop;
3166 spec->num_init_verbs++; 3175 spec->num_init_verbs++;
3167 spec->hp_laptop = 1; 3176 spec->hp_laptop = board_config == CXT5066_HP_LAPTOP;
3177 spec->asus = board_config == CXT5066_ASUS;
3168 spec->mixers[spec->num_mixers++] = cxt5066_mixer_master; 3178 spec->mixers[spec->num_mixers++] = cxt5066_mixer_master;
3169 spec->mixers[spec->num_mixers++] = cxt5066_mixers; 3179 spec->mixers[spec->num_mixers++] = cxt5066_mixers;
3170 /* no S/PDIF out */ 3180 /* no S/PDIF out */
3171 spec->multiout.dig_out_nid = 0; 3181 if (board_config == CXT5066_HP_LAPTOP)
3182 spec->multiout.dig_out_nid = 0;
3172 /* input source automatically selected */ 3183 /* input source automatically selected */
3173 spec->input_mux = NULL; 3184 spec->input_mux = NULL;
3174 spec->port_d_mode = 0; 3185 spec->port_d_mode = 0;
@@ -3196,9 +3207,9 @@ static int patch_cxt5066(struct hda_codec *codec)
3196 spec->capture_prepare = cxt5066_olpc_capture_prepare; 3207 spec->capture_prepare = cxt5066_olpc_capture_prepare;
3197 spec->capture_cleanup = cxt5066_olpc_capture_cleanup; 3208 spec->capture_cleanup = cxt5066_olpc_capture_cleanup;
3198 break; 3209 break;
3199 case CXT5066_DELL_VOSTO: 3210 case CXT5066_DELL_VOSTRO:
3200 codec->patch_ops.init = cxt5066_init; 3211 codec->patch_ops.init = cxt5066_init;
3201 codec->patch_ops.unsol_event = cxt5066_vostro_event; 3212 codec->patch_ops.unsol_event = cxt5066_unsol_event;
3202 spec->init_verbs[0] = cxt5066_init_verbs_vostro; 3213 spec->init_verbs[0] = cxt5066_init_verbs_vostro;
3203 spec->mixers[spec->num_mixers++] = cxt5066_mixer_master_olpc; 3214 spec->mixers[spec->num_mixers++] = cxt5066_mixer_master_olpc;
3204 spec->mixers[spec->num_mixers++] = cxt5066_mixers; 3215 spec->mixers[spec->num_mixers++] = cxt5066_mixers;
@@ -3215,7 +3226,7 @@ static int patch_cxt5066(struct hda_codec *codec)
3215 break; 3226 break;
3216 case CXT5066_IDEAPAD: 3227 case CXT5066_IDEAPAD:
3217 codec->patch_ops.init = cxt5066_init; 3228 codec->patch_ops.init = cxt5066_init;
3218 codec->patch_ops.unsol_event = cxt5066_ideapad_event; 3229 codec->patch_ops.unsol_event = cxt5066_unsol_event;
3219 spec->mixers[spec->num_mixers++] = cxt5066_mixer_master; 3230 spec->mixers[spec->num_mixers++] = cxt5066_mixer_master;
3220 spec->mixers[spec->num_mixers++] = cxt5066_mixers; 3231 spec->mixers[spec->num_mixers++] = cxt5066_mixers;
3221 spec->init_verbs[0] = cxt5066_init_verbs_ideapad; 3232 spec->init_verbs[0] = cxt5066_init_verbs_ideapad;
@@ -3231,7 +3242,7 @@ static int patch_cxt5066(struct hda_codec *codec)
3231 break; 3242 break;
3232 case CXT5066_THINKPAD: 3243 case CXT5066_THINKPAD:
3233 codec->patch_ops.init = cxt5066_init; 3244 codec->patch_ops.init = cxt5066_init;
3234 codec->patch_ops.unsol_event = cxt5066_thinkpad_event; 3245 codec->patch_ops.unsol_event = cxt5066_unsol_event;
3235 spec->mixers[spec->num_mixers++] = cxt5066_mixer_master; 3246 spec->mixers[spec->num_mixers++] = cxt5066_mixer_master;
3236 spec->mixers[spec->num_mixers++] = cxt5066_mixers; 3247 spec->mixers[spec->num_mixers++] = cxt5066_mixers;
3237 spec->init_verbs[0] = cxt5066_init_verbs_thinkpad; 3248 spec->init_verbs[0] = cxt5066_init_verbs_thinkpad;
@@ -3254,9 +3265,1117 @@ static int patch_cxt5066(struct hda_codec *codec)
3254} 3265}
3255 3266
3256/* 3267/*
3268 * Automatic parser for CX20641 & co
3269 */
3270
3271static int cx_auto_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
3272 struct hda_codec *codec,
3273 unsigned int stream_tag,
3274 unsigned int format,
3275 struct snd_pcm_substream *substream)
3276{
3277 struct conexant_spec *spec = codec->spec;
3278 hda_nid_t adc = spec->imux_info[spec->cur_mux[0]].adc;
3279 if (spec->adc_switching) {
3280 spec->cur_adc = adc;
3281 spec->cur_adc_stream_tag = stream_tag;
3282 spec->cur_adc_format = format;
3283 }
3284 snd_hda_codec_setup_stream(codec, adc, stream_tag, 0, format);
3285 return 0;
3286}
3287
3288static int cx_auto_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
3289 struct hda_codec *codec,
3290 struct snd_pcm_substream *substream)
3291{
3292 struct conexant_spec *spec = codec->spec;
3293 snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
3294 spec->cur_adc = 0;
3295 return 0;
3296}
3297
3298static const struct hda_pcm_stream cx_auto_pcm_analog_capture = {
3299 .substreams = 1,
3300 .channels_min = 2,
3301 .channels_max = 2,
3302 .nid = 0, /* fill later */
3303 .ops = {
3304 .prepare = cx_auto_capture_pcm_prepare,
3305 .cleanup = cx_auto_capture_pcm_cleanup
3306 },
3307};
3308
3309static const hda_nid_t cx_auto_adc_nids[] = { 0x14 };
3310
3311/* get the connection index of @nid in the widget @mux */
3312static int get_connection_index(struct hda_codec *codec, hda_nid_t mux,
3313 hda_nid_t nid)
3314{
3315 hda_nid_t conn[HDA_MAX_NUM_INPUTS];
3316 int i, nums;
3317
3318 nums = snd_hda_get_connections(codec, mux, conn, ARRAY_SIZE(conn));
3319 for (i = 0; i < nums; i++)
3320 if (conn[i] == nid)
3321 return i;
3322 return -1;
3323}
3324
3325/* get an unassigned DAC from the given list.
3326 * Return the nid if found and reduce the DAC list, or return zero if
3327 * not found
3328 */
3329static hda_nid_t get_unassigned_dac(struct hda_codec *codec, hda_nid_t pin,
3330 hda_nid_t *dacs, int *num_dacs)
3331{
3332 int i, nums = *num_dacs;
3333 hda_nid_t ret = 0;
3334
3335 for (i = 0; i < nums; i++) {
3336 if (get_connection_index(codec, pin, dacs[i]) >= 0) {
3337 ret = dacs[i];
3338 break;
3339 }
3340 }
3341 if (!ret)
3342 return 0;
3343 if (--nums > 0)
3344 memmove(dacs, dacs + 1, nums * sizeof(hda_nid_t));
3345 *num_dacs = nums;
3346 return ret;
3347}
3348
3349#define MAX_AUTO_DACS 5
3350
3351/* fill analog DAC list from the widget tree */
3352static int fill_cx_auto_dacs(struct hda_codec *codec, hda_nid_t *dacs)
3353{
3354 hda_nid_t nid, end_nid;
3355 int nums = 0;
3356
3357 end_nid = codec->start_nid + codec->num_nodes;
3358 for (nid = codec->start_nid; nid < end_nid; nid++) {
3359 unsigned int wcaps = get_wcaps(codec, nid);
3360 unsigned int type = get_wcaps_type(wcaps);
3361 if (type == AC_WID_AUD_OUT && !(wcaps & AC_WCAP_DIGITAL)) {
3362 dacs[nums++] = nid;
3363 if (nums >= MAX_AUTO_DACS)
3364 break;
3365 }
3366 }
3367 return nums;
3368}
3369
3370/* fill pin_dac_pair list from the pin and dac list */
3371static int fill_dacs_for_pins(struct hda_codec *codec, hda_nid_t *pins,
3372 int num_pins, hda_nid_t *dacs, int *rest,
3373 struct pin_dac_pair *filled, int type)
3374{
3375 int i, nums;
3376
3377 nums = 0;
3378 for (i = 0; i < num_pins; i++) {
3379 filled[nums].pin = pins[i];
3380 filled[nums].type = type;
3381 filled[nums].dac = get_unassigned_dac(codec, pins[i], dacs, rest);
3382 nums++;
3383 }
3384 return nums;
3385}
3386
3387/* parse analog output paths */
3388static void cx_auto_parse_output(struct hda_codec *codec)
3389{
3390 struct conexant_spec *spec = codec->spec;
3391 struct auto_pin_cfg *cfg = &spec->autocfg;
3392 hda_nid_t dacs[MAX_AUTO_DACS];
3393 int i, j, nums, rest;
3394
3395 rest = fill_cx_auto_dacs(codec, dacs);
3396 /* parse all analog output pins */
3397 nums = fill_dacs_for_pins(codec, cfg->line_out_pins, cfg->line_outs,
3398 dacs, &rest, spec->dac_info,
3399 AUTO_PIN_LINE_OUT);
3400 nums += fill_dacs_for_pins(codec, cfg->hp_pins, cfg->hp_outs,
3401 dacs, &rest, spec->dac_info + nums,
3402 AUTO_PIN_HP_OUT);
3403 nums += fill_dacs_for_pins(codec, cfg->speaker_pins, cfg->speaker_outs,
3404 dacs, &rest, spec->dac_info + nums,
3405 AUTO_PIN_SPEAKER_OUT);
3406 spec->dac_info_filled = nums;
3407 /* fill multiout struct */
3408 for (i = 0; i < nums; i++) {
3409 hda_nid_t dac = spec->dac_info[i].dac;
3410 if (!dac)
3411 continue;
3412 switch (spec->dac_info[i].type) {
3413 case AUTO_PIN_LINE_OUT:
3414 spec->private_dac_nids[spec->multiout.num_dacs] = dac;
3415 spec->multiout.num_dacs++;
3416 break;
3417 case AUTO_PIN_HP_OUT:
3418 case AUTO_PIN_SPEAKER_OUT:
3419 if (!spec->multiout.hp_nid) {
3420 spec->multiout.hp_nid = dac;
3421 break;
3422 }
3423 for (j = 0; j < ARRAY_SIZE(spec->multiout.extra_out_nid); j++)
3424 if (!spec->multiout.extra_out_nid[j]) {
3425 spec->multiout.extra_out_nid[j] = dac;
3426 break;
3427 }
3428 break;
3429 }
3430 }
3431 spec->multiout.dac_nids = spec->private_dac_nids;
3432 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
3433
3434 for (i = 0; i < cfg->hp_outs; i++) {
3435 if (is_jack_detectable(codec, cfg->hp_pins[i])) {
3436 spec->auto_mute = 1;
3437 break;
3438 }
3439 }
3440 if (spec->auto_mute &&
3441 cfg->line_out_pins[0] &&
3442 cfg->line_out_type != AUTO_PIN_SPEAKER_OUT &&
3443 cfg->line_out_pins[0] != cfg->hp_pins[0] &&
3444 cfg->line_out_pins[0] != cfg->speaker_pins[0]) {
3445 for (i = 0; i < cfg->line_outs; i++) {
3446 if (is_jack_detectable(codec, cfg->line_out_pins[i])) {
3447 spec->detect_line = 1;
3448 break;
3449 }
3450 }
3451 spec->automute_lines = spec->detect_line;
3452 }
3453
3454 spec->vmaster_nid = spec->private_dac_nids[0];
3455}
3456
3457static void cx_auto_turn_eapd(struct hda_codec *codec, int num_pins,
3458 hda_nid_t *pins, bool on);
3459
3460static void do_automute(struct hda_codec *codec, int num_pins,
3461 hda_nid_t *pins, bool on)
3462{
3463 int i;
3464 for (i = 0; i < num_pins; i++)
3465 snd_hda_codec_write(codec, pins[i], 0,
3466 AC_VERB_SET_PIN_WIDGET_CONTROL,
3467 on ? PIN_OUT : 0);
3468 cx_auto_turn_eapd(codec, num_pins, pins, on);
3469}
3470
3471static int detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
3472{
3473 int i, present = 0;
3474
3475 for (i = 0; i < num_pins; i++) {
3476 hda_nid_t nid = pins[i];
3477 if (!nid || !is_jack_detectable(codec, nid))
3478 break;
3479 snd_hda_input_jack_report(codec, nid);
3480 present |= snd_hda_jack_detect(codec, nid);
3481 }
3482 return present;
3483}
3484
3485/* auto-mute/unmute speaker and line outs according to headphone jack */
3486static void cx_auto_update_speakers(struct hda_codec *codec)
3487{
3488 struct conexant_spec *spec = codec->spec;
3489 struct auto_pin_cfg *cfg = &spec->autocfg;
3490 int on = 1;
3491
3492 /* turn on HP EAPD when HP jacks are present */
3493 if (spec->auto_mute)
3494 on = spec->hp_present;
3495 cx_auto_turn_eapd(codec, cfg->hp_outs, cfg->hp_pins, on);
3496 /* mute speakers in auto-mode if HP or LO jacks are plugged */
3497 if (spec->auto_mute)
3498 on = !(spec->hp_present ||
3499 (spec->detect_line && spec->line_present));
3500 do_automute(codec, cfg->speaker_outs, cfg->speaker_pins, on);
3501
3502 /* toggle line-out mutes if needed, too */
3503 /* if LO is a copy of either HP or Speaker, don't need to handle it */
3504 if (cfg->line_out_pins[0] == cfg->hp_pins[0] ||
3505 cfg->line_out_pins[0] == cfg->speaker_pins[0])
3506 return;
3507 if (spec->auto_mute) {
3508 /* mute LO in auto-mode when HP jack is present */
3509 if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT ||
3510 spec->automute_lines)
3511 on = !spec->hp_present;
3512 else
3513 on = 1;
3514 }
3515 do_automute(codec, cfg->line_outs, cfg->line_out_pins, on);
3516}
3517
3518static void cx_auto_hp_automute(struct hda_codec *codec)
3519{
3520 struct conexant_spec *spec = codec->spec;
3521 struct auto_pin_cfg *cfg = &spec->autocfg;
3522
3523 if (!spec->auto_mute)
3524 return;
3525 spec->hp_present = detect_jacks(codec, cfg->hp_outs, cfg->hp_pins);
3526 cx_auto_update_speakers(codec);
3527}
3528
3529static void cx_auto_line_automute(struct hda_codec *codec)
3530{
3531 struct conexant_spec *spec = codec->spec;
3532 struct auto_pin_cfg *cfg = &spec->autocfg;
3533
3534 if (!spec->auto_mute || !spec->detect_line)
3535 return;
3536 spec->line_present = detect_jacks(codec, cfg->line_outs,
3537 cfg->line_out_pins);
3538 cx_auto_update_speakers(codec);
3539}
3540
3541static int cx_automute_mode_info(struct snd_kcontrol *kcontrol,
3542 struct snd_ctl_elem_info *uinfo)
3543{
3544 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3545 struct conexant_spec *spec = codec->spec;
3546 static const char * const texts2[] = {
3547 "Disabled", "Enabled"
3548 };
3549 static const char * const texts3[] = {
3550 "Disabled", "Speaker Only", "Line-Out+Speaker"
3551 };
3552 const char * const *texts;
3553
3554 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3555 uinfo->count = 1;
3556 if (spec->automute_hp_lo) {
3557 uinfo->value.enumerated.items = 3;
3558 texts = texts3;
3559 } else {
3560 uinfo->value.enumerated.items = 2;
3561 texts = texts2;
3562 }
3563 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3564 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
3565 strcpy(uinfo->value.enumerated.name,
3566 texts[uinfo->value.enumerated.item]);
3567 return 0;
3568}
3569
3570static int cx_automute_mode_get(struct snd_kcontrol *kcontrol,
3571 struct snd_ctl_elem_value *ucontrol)
3572{
3573 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3574 struct conexant_spec *spec = codec->spec;
3575 unsigned int val;
3576 if (!spec->auto_mute)
3577 val = 0;
3578 else if (!spec->automute_lines)
3579 val = 1;
3580 else
3581 val = 2;
3582 ucontrol->value.enumerated.item[0] = val;
3583 return 0;
3584}
3585
3586static int cx_automute_mode_put(struct snd_kcontrol *kcontrol,
3587 struct snd_ctl_elem_value *ucontrol)
3588{
3589 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3590 struct conexant_spec *spec = codec->spec;
3591
3592 switch (ucontrol->value.enumerated.item[0]) {
3593 case 0:
3594 if (!spec->auto_mute)
3595 return 0;
3596 spec->auto_mute = 0;
3597 break;
3598 case 1:
3599 if (spec->auto_mute && !spec->automute_lines)
3600 return 0;
3601 spec->auto_mute = 1;
3602 spec->automute_lines = 0;
3603 break;
3604 case 2:
3605 if (!spec->automute_hp_lo)
3606 return -EINVAL;
3607 if (spec->auto_mute && spec->automute_lines)
3608 return 0;
3609 spec->auto_mute = 1;
3610 spec->automute_lines = 1;
3611 break;
3612 default:
3613 return -EINVAL;
3614 }
3615 cx_auto_update_speakers(codec);
3616 return 1;
3617}
3618
3619static const struct snd_kcontrol_new cx_automute_mode_enum[] = {
3620 {
3621 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3622 .name = "Auto-Mute Mode",
3623 .info = cx_automute_mode_info,
3624 .get = cx_automute_mode_get,
3625 .put = cx_automute_mode_put,
3626 },
3627 { }
3628};
3629
3630static int cx_auto_mux_enum_info(struct snd_kcontrol *kcontrol,
3631 struct snd_ctl_elem_info *uinfo)
3632{
3633 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3634 struct conexant_spec *spec = codec->spec;
3635
3636 return snd_hda_input_mux_info(&spec->private_imux, uinfo);
3637}
3638
3639static int cx_auto_mux_enum_get(struct snd_kcontrol *kcontrol,
3640 struct snd_ctl_elem_value *ucontrol)
3641{
3642 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3643 struct conexant_spec *spec = codec->spec;
3644
3645 ucontrol->value.enumerated.item[0] = spec->cur_mux[0];
3646 return 0;
3647}
3648
3649/* look for the route the given pin from mux and return the index;
3650 * if do_select is set, actually select the route.
3651 */
3652static int __select_input_connection(struct hda_codec *codec, hda_nid_t mux,
3653 hda_nid_t pin, hda_nid_t *srcp,
3654 bool do_select, int depth)
3655{
3656 hda_nid_t conn[HDA_MAX_NUM_INPUTS];
3657 int i, nums;
3658
3659 switch (get_wcaps_type(get_wcaps(codec, mux))) {
3660 case AC_WID_AUD_IN:
3661 case AC_WID_AUD_SEL:
3662 case AC_WID_AUD_MIX:
3663 break;
3664 default:
3665 return -1;
3666 }
3667
3668 nums = snd_hda_get_connections(codec, mux, conn, ARRAY_SIZE(conn));
3669 for (i = 0; i < nums; i++)
3670 if (conn[i] == pin) {
3671 if (do_select)
3672 snd_hda_codec_write(codec, mux, 0,
3673 AC_VERB_SET_CONNECT_SEL, i);
3674 if (srcp)
3675 *srcp = mux;
3676 return i;
3677 }
3678 depth++;
3679 if (depth == 2)
3680 return -1;
3681 for (i = 0; i < nums; i++) {
3682 int ret = __select_input_connection(codec, conn[i], pin, srcp,
3683 do_select, depth);
3684 if (ret >= 0) {
3685 if (do_select)
3686 snd_hda_codec_write(codec, mux, 0,
3687 AC_VERB_SET_CONNECT_SEL, i);
3688 return i;
3689 }
3690 }
3691 return -1;
3692}
3693
3694static void select_input_connection(struct hda_codec *codec, hda_nid_t mux,
3695 hda_nid_t pin)
3696{
3697 __select_input_connection(codec, mux, pin, NULL, true, 0);
3698}
3699
3700static int get_input_connection(struct hda_codec *codec, hda_nid_t mux,
3701 hda_nid_t pin)
3702{
3703 return __select_input_connection(codec, mux, pin, NULL, false, 0);
3704}
3705
3706static int cx_auto_mux_enum_update(struct hda_codec *codec,
3707 const struct hda_input_mux *imux,
3708 unsigned int idx)
3709{
3710 struct conexant_spec *spec = codec->spec;
3711 hda_nid_t adc;
3712 int changed = 1;
3713
3714 if (!imux->num_items)
3715 return 0;
3716 if (idx >= imux->num_items)
3717 idx = imux->num_items - 1;
3718 if (spec->cur_mux[0] == idx)
3719 changed = 0;
3720 adc = spec->imux_info[idx].adc;
3721 select_input_connection(codec, spec->imux_info[idx].adc,
3722 spec->imux_info[idx].pin);
3723 if (spec->cur_adc && spec->cur_adc != adc) {
3724 /* stream is running, let's swap the current ADC */
3725 __snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
3726 spec->cur_adc = adc;
3727 snd_hda_codec_setup_stream(codec, adc,
3728 spec->cur_adc_stream_tag, 0,
3729 spec->cur_adc_format);
3730 }
3731 spec->cur_mux[0] = idx;
3732 return changed;
3733}
3734
3735static int cx_auto_mux_enum_put(struct snd_kcontrol *kcontrol,
3736 struct snd_ctl_elem_value *ucontrol)
3737{
3738 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3739 struct conexant_spec *spec = codec->spec;
3740
3741 return cx_auto_mux_enum_update(codec, &spec->private_imux,
3742 ucontrol->value.enumerated.item[0]);
3743}
3744
3745static const struct snd_kcontrol_new cx_auto_capture_mixers[] = {
3746 {
3747 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3748 .name = "Capture Source",
3749 .info = cx_auto_mux_enum_info,
3750 .get = cx_auto_mux_enum_get,
3751 .put = cx_auto_mux_enum_put
3752 },
3753 {}
3754};
3755
3756static bool select_automic(struct hda_codec *codec, int idx, bool detect)
3757{
3758 struct conexant_spec *spec = codec->spec;
3759 if (idx < 0)
3760 return false;
3761 if (detect && !snd_hda_jack_detect(codec, spec->imux_info[idx].pin))
3762 return false;
3763 cx_auto_mux_enum_update(codec, &spec->private_imux, idx);
3764 return true;
3765}
3766
3767/* automatic switch internal and external mic */
3768static void cx_auto_automic(struct hda_codec *codec)
3769{
3770 struct conexant_spec *spec = codec->spec;
3771
3772 if (!spec->auto_mic)
3773 return;
3774 if (!select_automic(codec, spec->auto_mic_ext, true))
3775 if (!select_automic(codec, spec->auto_mic_dock, true))
3776 select_automic(codec, spec->auto_mic_int, false);
3777}
3778
3779static void cx_auto_unsol_event(struct hda_codec *codec, unsigned int res)
3780{
3781 int nid = (res & AC_UNSOL_RES_SUBTAG) >> 20;
3782 switch (res >> 26) {
3783 case CONEXANT_HP_EVENT:
3784 cx_auto_hp_automute(codec);
3785 break;
3786 case CONEXANT_LINE_EVENT:
3787 cx_auto_line_automute(codec);
3788 break;
3789 case CONEXANT_MIC_EVENT:
3790 cx_auto_automic(codec);
3791 snd_hda_input_jack_report(codec, nid);
3792 break;
3793 }
3794}
3795
3796/* check whether the pin config is suitable for auto-mic switching;
3797 * auto-mic is enabled only when one int-mic and one ext- and/or
3798 * one dock-mic exist
3799 */
3800static void cx_auto_check_auto_mic(struct hda_codec *codec)
3801{
3802 struct conexant_spec *spec = codec->spec;
3803 int pset[INPUT_PIN_ATTR_NORMAL + 1];
3804 int i;
3805
3806 for (i = 0; i < ARRAY_SIZE(pset); i++)
3807 pset[i] = -1;
3808 for (i = 0; i < spec->private_imux.num_items; i++) {
3809 hda_nid_t pin = spec->imux_info[i].pin;
3810 unsigned int def_conf = snd_hda_codec_get_pincfg(codec, pin);
3811 int type, attr;
3812 attr = snd_hda_get_input_pin_attr(def_conf);
3813 if (attr == INPUT_PIN_ATTR_UNUSED)
3814 return; /* invalid entry */
3815 if (attr > INPUT_PIN_ATTR_NORMAL)
3816 attr = INPUT_PIN_ATTR_NORMAL;
3817 if (attr != INPUT_PIN_ATTR_INT &&
3818 !is_jack_detectable(codec, pin))
3819 return; /* non-detectable pin */
3820 type = get_defcfg_device(def_conf);
3821 if (type != AC_JACK_MIC_IN &&
3822 (attr != INPUT_PIN_ATTR_DOCK || type != AC_JACK_LINE_IN))
3823 return; /* no valid input type */
3824 if (pset[attr] >= 0)
3825 return; /* already occupied */
3826 pset[attr] = i;
3827 }
3828 if (pset[INPUT_PIN_ATTR_INT] < 0 ||
3829 (pset[INPUT_PIN_ATTR_NORMAL] < 0 && pset[INPUT_PIN_ATTR_DOCK]))
3830 return; /* no input to switch*/
3831 spec->auto_mic = 1;
3832 spec->auto_mic_ext = pset[INPUT_PIN_ATTR_NORMAL];
3833 spec->auto_mic_dock = pset[INPUT_PIN_ATTR_DOCK];
3834 spec->auto_mic_int = pset[INPUT_PIN_ATTR_INT];
3835}
3836
3837static void cx_auto_parse_input(struct hda_codec *codec)
3838{
3839 struct conexant_spec *spec = codec->spec;
3840 struct auto_pin_cfg *cfg = &spec->autocfg;
3841 struct hda_input_mux *imux;
3842 int i, j;
3843
3844 imux = &spec->private_imux;
3845 for (i = 0; i < cfg->num_inputs; i++) {
3846 for (j = 0; j < spec->num_adc_nids; j++) {
3847 hda_nid_t adc = spec->adc_nids[j];
3848 int idx = get_input_connection(codec, adc,
3849 cfg->inputs[i].pin);
3850 if (idx >= 0) {
3851 const char *label;
3852 label = hda_get_autocfg_input_label(codec, cfg, i);
3853 spec->imux_info[imux->num_items].index = i;
3854 spec->imux_info[imux->num_items].boost = 0;
3855 spec->imux_info[imux->num_items].adc = adc;
3856 spec->imux_info[imux->num_items].pin =
3857 cfg->inputs[i].pin;
3858 snd_hda_add_imux_item(imux, label, idx, NULL);
3859 break;
3860 }
3861 }
3862 }
3863 if (imux->num_items >= 2 && cfg->num_inputs == imux->num_items)
3864 cx_auto_check_auto_mic(codec);
3865 if (imux->num_items > 1 && !spec->auto_mic) {
3866 for (i = 1; i < imux->num_items; i++) {
3867 if (spec->imux_info[i].adc != spec->imux_info[0].adc) {
3868 spec->adc_switching = 1;
3869 break;
3870 }
3871 }
3872 }
3873}
3874
3875/* get digital-input audio widget corresponding to the given pin */
3876static hda_nid_t cx_auto_get_dig_in(struct hda_codec *codec, hda_nid_t pin)
3877{
3878 hda_nid_t nid, end_nid;
3879
3880 end_nid = codec->start_nid + codec->num_nodes;
3881 for (nid = codec->start_nid; nid < end_nid; nid++) {
3882 unsigned int wcaps = get_wcaps(codec, nid);
3883 unsigned int type = get_wcaps_type(wcaps);
3884 if (type == AC_WID_AUD_IN && (wcaps & AC_WCAP_DIGITAL)) {
3885 if (get_connection_index(codec, nid, pin) >= 0)
3886 return nid;
3887 }
3888 }
3889 return 0;
3890}
3891
3892static void cx_auto_parse_digital(struct hda_codec *codec)
3893{
3894 struct conexant_spec *spec = codec->spec;
3895 struct auto_pin_cfg *cfg = &spec->autocfg;
3896 hda_nid_t nid;
3897
3898 if (cfg->dig_outs &&
3899 snd_hda_get_connections(codec, cfg->dig_out_pins[0], &nid, 1) == 1)
3900 spec->multiout.dig_out_nid = nid;
3901 if (cfg->dig_in_pin)
3902 spec->dig_in_nid = cx_auto_get_dig_in(codec, cfg->dig_in_pin);
3903}
3904
3905#ifdef CONFIG_SND_HDA_INPUT_BEEP
3906static void cx_auto_parse_beep(struct hda_codec *codec)
3907{
3908 struct conexant_spec *spec = codec->spec;
3909 hda_nid_t nid, end_nid;
3910
3911 end_nid = codec->start_nid + codec->num_nodes;
3912 for (nid = codec->start_nid; nid < end_nid; nid++)
3913 if (get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_BEEP) {
3914 set_beep_amp(spec, nid, 0, HDA_OUTPUT);
3915 break;
3916 }
3917}
3918#else
3919#define cx_auto_parse_beep(codec)
3920#endif
3921
3922static int cx_auto_parse_auto_config(struct hda_codec *codec)
3923{
3924 struct conexant_spec *spec = codec->spec;
3925 int err;
3926
3927 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
3928 if (err < 0)
3929 return err;
3930
3931 cx_auto_parse_output(codec);
3932 cx_auto_parse_input(codec);
3933 cx_auto_parse_digital(codec);
3934 cx_auto_parse_beep(codec);
3935 return 0;
3936}
3937
3938static void cx_auto_turn_eapd(struct hda_codec *codec, int num_pins,
3939 hda_nid_t *pins, bool on)
3940{
3941 int i;
3942 for (i = 0; i < num_pins; i++) {
3943 if (snd_hda_query_pin_caps(codec, pins[i]) & AC_PINCAP_EAPD)
3944 snd_hda_codec_write(codec, pins[i], 0,
3945 AC_VERB_SET_EAPD_BTLENABLE,
3946 on ? 0x02 : 0);
3947 }
3948}
3949
3950static void select_connection(struct hda_codec *codec, hda_nid_t pin,
3951 hda_nid_t src)
3952{
3953 int idx = get_connection_index(codec, pin, src);
3954 if (idx >= 0)
3955 snd_hda_codec_write(codec, pin, 0,
3956 AC_VERB_SET_CONNECT_SEL, idx);
3957}
3958
3959static void mute_outputs(struct hda_codec *codec, int num_nids,
3960 const hda_nid_t *nids)
3961{
3962 int i, val;
3963
3964 for (i = 0; i < num_nids; i++) {
3965 hda_nid_t nid = nids[i];
3966 if (!(get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
3967 continue;
3968 if (query_amp_caps(codec, nid, HDA_OUTPUT) & AC_AMPCAP_MUTE)
3969 val = AMP_OUT_MUTE;
3970 else
3971 val = AMP_OUT_ZERO;
3972 snd_hda_codec_write(codec, nid, 0,
3973 AC_VERB_SET_AMP_GAIN_MUTE, val);
3974 }
3975}
3976
3977static void enable_unsol_pins(struct hda_codec *codec, int num_pins,
3978 hda_nid_t *pins, unsigned int tag)
3979{
3980 int i;
3981 for (i = 0; i < num_pins; i++)
3982 snd_hda_codec_write(codec, pins[i], 0,
3983 AC_VERB_SET_UNSOLICITED_ENABLE,
3984 AC_USRSP_EN | tag);
3985}
3986
3987static void cx_auto_init_output(struct hda_codec *codec)
3988{
3989 struct conexant_spec *spec = codec->spec;
3990 struct auto_pin_cfg *cfg = &spec->autocfg;
3991 hda_nid_t nid;
3992 int i;
3993
3994 mute_outputs(codec, spec->multiout.num_dacs, spec->multiout.dac_nids);
3995 for (i = 0; i < cfg->hp_outs; i++)
3996 snd_hda_codec_write(codec, cfg->hp_pins[i], 0,
3997 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP);
3998 mute_outputs(codec, cfg->hp_outs, cfg->hp_pins);
3999 mute_outputs(codec, cfg->line_outs, cfg->line_out_pins);
4000 mute_outputs(codec, cfg->speaker_outs, cfg->speaker_pins);
4001 for (i = 0; i < spec->dac_info_filled; i++) {
4002 nid = spec->dac_info[i].dac;
4003 if (!nid)
4004 nid = spec->multiout.dac_nids[0];
4005 select_connection(codec, spec->dac_info[i].pin, nid);
4006 }
4007 if (spec->auto_mute) {
4008 enable_unsol_pins(codec, cfg->hp_outs, cfg->hp_pins,
4009 CONEXANT_HP_EVENT);
4010 spec->hp_present = detect_jacks(codec, cfg->hp_outs,
4011 cfg->hp_pins);
4012 if (spec->detect_line) {
4013 enable_unsol_pins(codec, cfg->line_outs,
4014 cfg->line_out_pins,
4015 CONEXANT_LINE_EVENT);
4016 spec->line_present =
4017 detect_jacks(codec, cfg->line_outs,
4018 cfg->line_out_pins);
4019 }
4020 }
4021 cx_auto_update_speakers(codec);
4022}
4023
4024static void cx_auto_init_input(struct hda_codec *codec)
4025{
4026 struct conexant_spec *spec = codec->spec;
4027 struct auto_pin_cfg *cfg = &spec->autocfg;
4028 int i, val;
4029
4030 for (i = 0; i < spec->num_adc_nids; i++) {
4031 hda_nid_t nid = spec->adc_nids[i];
4032 if (!(get_wcaps(codec, nid) & AC_WCAP_IN_AMP))
4033 continue;
4034 if (query_amp_caps(codec, nid, HDA_INPUT) & AC_AMPCAP_MUTE)
4035 val = AMP_IN_MUTE(0);
4036 else
4037 val = AMP_IN_UNMUTE(0);
4038 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
4039 val);
4040 }
4041
4042 for (i = 0; i < cfg->num_inputs; i++) {
4043 unsigned int type;
4044 if (cfg->inputs[i].type == AUTO_PIN_MIC)
4045 type = PIN_VREF80;
4046 else
4047 type = PIN_IN;
4048 snd_hda_codec_write(codec, cfg->inputs[i].pin, 0,
4049 AC_VERB_SET_PIN_WIDGET_CONTROL, type);
4050 }
4051
4052 if (spec->auto_mic) {
4053 if (spec->auto_mic_ext >= 0) {
4054 snd_hda_codec_write(codec,
4055 cfg->inputs[spec->auto_mic_ext].pin, 0,
4056 AC_VERB_SET_UNSOLICITED_ENABLE,
4057 AC_USRSP_EN | CONEXANT_MIC_EVENT);
4058 }
4059 if (spec->auto_mic_dock >= 0) {
4060 snd_hda_codec_write(codec,
4061 cfg->inputs[spec->auto_mic_dock].pin, 0,
4062 AC_VERB_SET_UNSOLICITED_ENABLE,
4063 AC_USRSP_EN | CONEXANT_MIC_EVENT);
4064 }
4065 cx_auto_automic(codec);
4066 } else {
4067 select_input_connection(codec, spec->imux_info[0].adc,
4068 spec->imux_info[0].pin);
4069 }
4070}
4071
4072static void cx_auto_init_digital(struct hda_codec *codec)
4073{
4074 struct conexant_spec *spec = codec->spec;
4075 struct auto_pin_cfg *cfg = &spec->autocfg;
4076
4077 if (spec->multiout.dig_out_nid)
4078 snd_hda_codec_write(codec, cfg->dig_out_pins[0], 0,
4079 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
4080 if (spec->dig_in_nid)
4081 snd_hda_codec_write(codec, cfg->dig_in_pin, 0,
4082 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN);
4083}
4084
4085static int cx_auto_init(struct hda_codec *codec)
4086{
4087 /*snd_hda_sequence_write(codec, cx_auto_init_verbs);*/
4088 cx_auto_init_output(codec);
4089 cx_auto_init_input(codec);
4090 cx_auto_init_digital(codec);
4091 return 0;
4092}
4093
4094static int cx_auto_add_volume_idx(struct hda_codec *codec, const char *basename,
4095 const char *dir, int cidx,
4096 hda_nid_t nid, int hda_dir, int amp_idx)
4097{
4098 static char name[32];
4099 static struct snd_kcontrol_new knew[] = {
4100 HDA_CODEC_VOLUME(name, 0, 0, 0),
4101 HDA_CODEC_MUTE(name, 0, 0, 0),
4102 };
4103 static const char * const sfx[2] = { "Volume", "Switch" };
4104 int i, err;
4105
4106 for (i = 0; i < 2; i++) {
4107 struct snd_kcontrol *kctl;
4108 knew[i].private_value = HDA_COMPOSE_AMP_VAL(nid, 3, amp_idx,
4109 hda_dir);
4110 knew[i].subdevice = HDA_SUBDEV_AMP_FLAG;
4111 knew[i].index = cidx;
4112 snprintf(name, sizeof(name), "%s%s %s", basename, dir, sfx[i]);
4113 kctl = snd_ctl_new1(&knew[i], codec);
4114 if (!kctl)
4115 return -ENOMEM;
4116 err = snd_hda_ctl_add(codec, nid, kctl);
4117 if (err < 0)
4118 return err;
4119 if (!(query_amp_caps(codec, nid, hda_dir) & AC_AMPCAP_MUTE))
4120 break;
4121 }
4122 return 0;
4123}
4124
4125#define cx_auto_add_volume(codec, str, dir, cidx, nid, hda_dir) \
4126 cx_auto_add_volume_idx(codec, str, dir, cidx, nid, hda_dir, 0)
4127
4128#define cx_auto_add_pb_volume(codec, nid, str, idx) \
4129 cx_auto_add_volume(codec, str, " Playback", idx, nid, HDA_OUTPUT)
4130
4131static int try_add_pb_volume(struct hda_codec *codec, hda_nid_t dac,
4132 hda_nid_t pin, const char *name, int idx)
4133{
4134 unsigned int caps;
4135 caps = query_amp_caps(codec, dac, HDA_OUTPUT);
4136 if (caps & AC_AMPCAP_NUM_STEPS)
4137 return cx_auto_add_pb_volume(codec, dac, name, idx);
4138 caps = query_amp_caps(codec, pin, HDA_OUTPUT);
4139 if (caps & AC_AMPCAP_NUM_STEPS)
4140 return cx_auto_add_pb_volume(codec, pin, name, idx);
4141 return 0;
4142}
4143
4144static int cx_auto_build_output_controls(struct hda_codec *codec)
4145{
4146 struct conexant_spec *spec = codec->spec;
4147 int i, err;
4148 int num_line = 0, num_hp = 0, num_spk = 0;
4149 static const char * const texts[3] = { "Front", "Surround", "CLFE" };
4150
4151 if (spec->dac_info_filled == 1)
4152 return try_add_pb_volume(codec, spec->dac_info[0].dac,
4153 spec->dac_info[0].pin,
4154 "Master", 0);
4155
4156 for (i = 0; i < spec->dac_info_filled; i++) {
4157 const char *label;
4158 int idx, type;
4159 if (!spec->dac_info[i].dac)
4160 continue;
4161 type = spec->dac_info[i].type;
4162 if (type == AUTO_PIN_LINE_OUT)
4163 type = spec->autocfg.line_out_type;
4164 switch (type) {
4165 case AUTO_PIN_LINE_OUT:
4166 default:
4167 label = texts[num_line++];
4168 idx = 0;
4169 break;
4170 case AUTO_PIN_HP_OUT:
4171 label = "Headphone";
4172 idx = num_hp++;
4173 break;
4174 case AUTO_PIN_SPEAKER_OUT:
4175 label = "Speaker";
4176 idx = num_spk++;
4177 break;
4178 }
4179 err = try_add_pb_volume(codec, spec->dac_info[i].dac,
4180 spec->dac_info[i].pin,
4181 label, idx);
4182 if (err < 0)
4183 return err;
4184 }
4185
4186 if (spec->auto_mute) {
4187 err = snd_hda_add_new_ctls(codec, cx_automute_mode_enum);
4188 if (err < 0)
4189 return err;
4190 }
4191
4192 return 0;
4193}
4194
4195static int cx_auto_add_capture_volume(struct hda_codec *codec, hda_nid_t nid,
4196 const char *label, const char *pfx,
4197 int cidx)
4198{
4199 struct conexant_spec *spec = codec->spec;
4200 int i;
4201
4202 for (i = 0; i < spec->num_adc_nids; i++) {
4203 hda_nid_t adc_nid = spec->adc_nids[i];
4204 int idx = get_input_connection(codec, adc_nid, nid);
4205 if (idx < 0)
4206 continue;
4207 return cx_auto_add_volume_idx(codec, label, pfx,
4208 cidx, adc_nid, HDA_INPUT, idx);
4209 }
4210 return 0;
4211}
4212
4213static int cx_auto_add_boost_volume(struct hda_codec *codec, int idx,
4214 const char *label, int cidx)
4215{
4216 struct conexant_spec *spec = codec->spec;
4217 hda_nid_t mux, nid;
4218 int i, con;
4219
4220 nid = spec->imux_info[idx].pin;
4221 if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP)
4222 return cx_auto_add_volume(codec, label, " Boost", cidx,
4223 nid, HDA_INPUT);
4224 con = __select_input_connection(codec, spec->imux_info[idx].adc, nid,
4225 &mux, false, 0);
4226 if (con < 0)
4227 return 0;
4228 for (i = 0; i < idx; i++) {
4229 if (spec->imux_info[i].boost == mux)
4230 return 0; /* already present */
4231 }
4232
4233 if (get_wcaps(codec, mux) & AC_WCAP_OUT_AMP) {
4234 spec->imux_info[idx].boost = mux;
4235 return cx_auto_add_volume(codec, label, " Boost", 0,
4236 mux, HDA_OUTPUT);
4237 }
4238 return 0;
4239}
4240
4241static int cx_auto_build_input_controls(struct hda_codec *codec)
4242{
4243 struct conexant_spec *spec = codec->spec;
4244 struct hda_input_mux *imux = &spec->private_imux;
4245 const char *prev_label;
4246 int input_conn[HDA_MAX_NUM_INPUTS];
4247 int i, err, cidx;
4248 int multi_connection;
4249
4250 multi_connection = 0;
4251 for (i = 0; i < imux->num_items; i++) {
4252 cidx = get_input_connection(codec, spec->imux_info[i].adc,
4253 spec->imux_info[i].pin);
4254 input_conn[i] = (spec->imux_info[i].adc << 8) | cidx;
4255 if (i > 0 && input_conn[i] != input_conn[0])
4256 multi_connection = 1;
4257 }
4258
4259 prev_label = NULL;
4260 cidx = 0;
4261 for (i = 0; i < imux->num_items; i++) {
4262 hda_nid_t nid = spec->imux_info[i].pin;
4263 const char *label;
4264
4265 label = hda_get_autocfg_input_label(codec, &spec->autocfg,
4266 spec->imux_info[i].index);
4267 if (label == prev_label)
4268 cidx++;
4269 else
4270 cidx = 0;
4271 prev_label = label;
4272
4273 err = cx_auto_add_boost_volume(codec, i, label, cidx);
4274 if (err < 0)
4275 return err;
4276
4277 if (!multi_connection) {
4278 if (i > 0)
4279 continue;
4280 err = cx_auto_add_capture_volume(codec, nid,
4281 "Capture", "", cidx);
4282 } else {
4283 err = cx_auto_add_capture_volume(codec, nid,
4284 label, " Capture", cidx);
4285 }
4286 if (err < 0)
4287 return err;
4288 }
4289
4290 if (spec->private_imux.num_items > 1 && !spec->auto_mic) {
4291 err = snd_hda_add_new_ctls(codec, cx_auto_capture_mixers);
4292 if (err < 0)
4293 return err;
4294 }
4295
4296 return 0;
4297}
4298
4299static int cx_auto_build_controls(struct hda_codec *codec)
4300{
4301 int err;
4302
4303 err = cx_auto_build_output_controls(codec);
4304 if (err < 0)
4305 return err;
4306 err = cx_auto_build_input_controls(codec);
4307 if (err < 0)
4308 return err;
4309 return conexant_build_controls(codec);
4310}
4311
4312static int cx_auto_search_adcs(struct hda_codec *codec)
4313{
4314 struct conexant_spec *spec = codec->spec;
4315 hda_nid_t nid, end_nid;
4316
4317 end_nid = codec->start_nid + codec->num_nodes;
4318 for (nid = codec->start_nid; nid < end_nid; nid++) {
4319 unsigned int caps = get_wcaps(codec, nid);
4320 if (get_wcaps_type(caps) != AC_WID_AUD_IN)
4321 continue;
4322 if (caps & AC_WCAP_DIGITAL)
4323 continue;
4324 if (snd_BUG_ON(spec->num_adc_nids >=
4325 ARRAY_SIZE(spec->private_adc_nids)))
4326 break;
4327 spec->private_adc_nids[spec->num_adc_nids++] = nid;
4328 }
4329 spec->adc_nids = spec->private_adc_nids;
4330 return 0;
4331}
4332
4333
4334static const struct hda_codec_ops cx_auto_patch_ops = {
4335 .build_controls = cx_auto_build_controls,
4336 .build_pcms = conexant_build_pcms,
4337 .init = cx_auto_init,
4338 .free = conexant_free,
4339 .unsol_event = cx_auto_unsol_event,
4340#ifdef CONFIG_SND_HDA_POWER_SAVE
4341 .suspend = conexant_suspend,
4342#endif
4343 .reboot_notify = snd_hda_shutup_pins,
4344};
4345
4346static int patch_conexant_auto(struct hda_codec *codec)
4347{
4348 struct conexant_spec *spec;
4349 int err;
4350
4351 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
4352 codec->chip_name);
4353
4354 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4355 if (!spec)
4356 return -ENOMEM;
4357 codec->spec = spec;
4358 codec->pin_amp_workaround = 1;
4359 err = cx_auto_search_adcs(codec);
4360 if (err < 0)
4361 return err;
4362 err = cx_auto_parse_auto_config(codec);
4363 if (err < 0) {
4364 kfree(codec->spec);
4365 codec->spec = NULL;
4366 return err;
4367 }
4368 spec->capture_stream = &cx_auto_pcm_analog_capture;
4369 codec->patch_ops = cx_auto_patch_ops;
4370 if (spec->beep_amp)
4371 snd_hda_attach_beep_device(codec, spec->beep_amp);
4372 return 0;
4373}
4374
4375/*
3257 */ 4376 */
3258 4377
3259static struct hda_codec_preset snd_hda_preset_conexant[] = { 4378static const struct hda_codec_preset snd_hda_preset_conexant[] = {
3260 { .id = 0x14f15045, .name = "CX20549 (Venice)", 4379 { .id = 0x14f15045, .name = "CX20549 (Venice)",
3261 .patch = patch_cxt5045 }, 4380 .patch = patch_cxt5045 },
3262 { .id = 0x14f15047, .name = "CX20551 (Waikiki)", 4381 { .id = 0x14f15047, .name = "CX20551 (Waikiki)",
@@ -3271,6 +4390,26 @@ static struct hda_codec_preset snd_hda_preset_conexant[] = {
3271 .patch = patch_cxt5066 }, 4390 .patch = patch_cxt5066 },
3272 { .id = 0x14f15069, .name = "CX20585", 4391 { .id = 0x14f15069, .name = "CX20585",
3273 .patch = patch_cxt5066 }, 4392 .patch = patch_cxt5066 },
4393 { .id = 0x14f1506c, .name = "CX20588",
4394 .patch = patch_cxt5066 },
4395 { .id = 0x14f1506e, .name = "CX20590",
4396 .patch = patch_cxt5066 },
4397 { .id = 0x14f15097, .name = "CX20631",
4398 .patch = patch_conexant_auto },
4399 { .id = 0x14f15098, .name = "CX20632",
4400 .patch = patch_conexant_auto },
4401 { .id = 0x14f150a1, .name = "CX20641",
4402 .patch = patch_conexant_auto },
4403 { .id = 0x14f150a2, .name = "CX20642",
4404 .patch = patch_conexant_auto },
4405 { .id = 0x14f150ab, .name = "CX20651",
4406 .patch = patch_conexant_auto },
4407 { .id = 0x14f150ac, .name = "CX20652",
4408 .patch = patch_conexant_auto },
4409 { .id = 0x14f150b8, .name = "CX20664",
4410 .patch = patch_conexant_auto },
4411 { .id = 0x14f150b9, .name = "CX20665",
4412 .patch = patch_conexant_auto },
3274 {} /* terminator */ 4413 {} /* terminator */
3275}; 4414};
3276 4415
@@ -3281,6 +4420,16 @@ MODULE_ALIAS("snd-hda-codec-id:14f15066");
3281MODULE_ALIAS("snd-hda-codec-id:14f15067"); 4420MODULE_ALIAS("snd-hda-codec-id:14f15067");
3282MODULE_ALIAS("snd-hda-codec-id:14f15068"); 4421MODULE_ALIAS("snd-hda-codec-id:14f15068");
3283MODULE_ALIAS("snd-hda-codec-id:14f15069"); 4422MODULE_ALIAS("snd-hda-codec-id:14f15069");
4423MODULE_ALIAS("snd-hda-codec-id:14f1506c");
4424MODULE_ALIAS("snd-hda-codec-id:14f1506e");
4425MODULE_ALIAS("snd-hda-codec-id:14f15097");
4426MODULE_ALIAS("snd-hda-codec-id:14f15098");
4427MODULE_ALIAS("snd-hda-codec-id:14f150a1");
4428MODULE_ALIAS("snd-hda-codec-id:14f150a2");
4429MODULE_ALIAS("snd-hda-codec-id:14f150ab");
4430MODULE_ALIAS("snd-hda-codec-id:14f150ac");
4431MODULE_ALIAS("snd-hda-codec-id:14f150b8");
4432MODULE_ALIAS("snd-hda-codec-id:14f150b9");
3284 4433
3285MODULE_LICENSE("GPL"); 4434MODULE_LICENSE("GPL");
3286MODULE_DESCRIPTION("Conexant HD-audio codec"); 4435MODULE_DESCRIPTION("Conexant HD-audio codec");