diff options
Diffstat (limited to 'sound/pci/hda/patch_conexant.c')
-rw-r--r-- | sound/pci/hda/patch_conexant.c | 401 |
1 files changed, 217 insertions, 184 deletions
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 75de40aaab0a..56ce19e68cb5 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -58,6 +58,7 @@ struct conexant_spec { | |||
58 | 58 | ||
59 | struct snd_kcontrol_new *mixers[5]; | 59 | struct snd_kcontrol_new *mixers[5]; |
60 | int num_mixers; | 60 | int num_mixers; |
61 | hda_nid_t vmaster_nid; | ||
61 | 62 | ||
62 | const struct hda_verb *init_verbs[5]; /* initialization verbs | 63 | const struct hda_verb *init_verbs[5]; /* initialization verbs |
63 | * don't forget NULL | 64 | * don't forget NULL |
@@ -72,6 +73,7 @@ struct conexant_spec { | |||
72 | */ | 73 | */ |
73 | unsigned int cur_eapd; | 74 | unsigned int cur_eapd; |
74 | unsigned int hp_present; | 75 | unsigned int hp_present; |
76 | unsigned int no_auto_mic; | ||
75 | unsigned int need_dac_fix; | 77 | unsigned int need_dac_fix; |
76 | 78 | ||
77 | /* capture */ | 79 | /* capture */ |
@@ -347,12 +349,21 @@ static int conexant_mux_enum_put(struct snd_kcontrol *kcontrol, | |||
347 | &spec->cur_mux[adc_idx]); | 349 | &spec->cur_mux[adc_idx]); |
348 | } | 350 | } |
349 | 351 | ||
352 | #ifdef CONFIG_SND_JACK | ||
353 | static void conexant_free_jack_priv(struct snd_jack *jack) | ||
354 | { | ||
355 | struct conexant_jack *jacks = jack->private_data; | ||
356 | jacks->nid = 0; | ||
357 | jacks->jack = NULL; | ||
358 | } | ||
359 | |||
350 | static int conexant_add_jack(struct hda_codec *codec, | 360 | static int conexant_add_jack(struct hda_codec *codec, |
351 | hda_nid_t nid, int type) | 361 | hda_nid_t nid, int type) |
352 | { | 362 | { |
353 | struct conexant_spec *spec; | 363 | struct conexant_spec *spec; |
354 | struct conexant_jack *jack; | 364 | struct conexant_jack *jack; |
355 | const char *name; | 365 | const char *name; |
366 | int err; | ||
356 | 367 | ||
357 | spec = codec->spec; | 368 | spec = codec->spec; |
358 | snd_array_init(&spec->jacks, sizeof(*jack), 32); | 369 | snd_array_init(&spec->jacks, sizeof(*jack), 32); |
@@ -365,7 +376,12 @@ static int conexant_add_jack(struct hda_codec *codec, | |||
365 | jack->nid = nid; | 376 | jack->nid = nid; |
366 | jack->type = type; | 377 | jack->type = type; |
367 | 378 | ||
368 | return snd_jack_new(codec->bus->card, name, type, &jack->jack); | 379 | err = snd_jack_new(codec->bus->card, name, type, &jack->jack); |
380 | if (err < 0) | ||
381 | return err; | ||
382 | jack->jack->private_data = jack; | ||
383 | jack->jack->private_free = conexant_free_jack_priv; | ||
384 | return 0; | ||
369 | } | 385 | } |
370 | 386 | ||
371 | static void conexant_report_jack(struct hda_codec *codec, hda_nid_t nid) | 387 | static void conexant_report_jack(struct hda_codec *codec, hda_nid_t nid) |
@@ -394,7 +410,6 @@ static void conexant_report_jack(struct hda_codec *codec, hda_nid_t nid) | |||
394 | 410 | ||
395 | static int conexant_init_jacks(struct hda_codec *codec) | 411 | static int conexant_init_jacks(struct hda_codec *codec) |
396 | { | 412 | { |
397 | #ifdef CONFIG_SND_JACK | ||
398 | struct conexant_spec *spec = codec->spec; | 413 | struct conexant_spec *spec = codec->spec; |
399 | int i; | 414 | int i; |
400 | 415 | ||
@@ -422,10 +437,19 @@ static int conexant_init_jacks(struct hda_codec *codec) | |||
422 | ++hv; | 437 | ++hv; |
423 | } | 438 | } |
424 | } | 439 | } |
425 | #endif | ||
426 | return 0; | 440 | return 0; |
427 | 441 | ||
428 | } | 442 | } |
443 | #else | ||
444 | static inline void conexant_report_jack(struct hda_codec *codec, hda_nid_t nid) | ||
445 | { | ||
446 | } | ||
447 | |||
448 | static inline int conexant_init_jacks(struct hda_codec *codec) | ||
449 | { | ||
450 | return 0; | ||
451 | } | ||
452 | #endif | ||
429 | 453 | ||
430 | static int conexant_init(struct hda_codec *codec) | 454 | static int conexant_init(struct hda_codec *codec) |
431 | { | 455 | { |
@@ -444,14 +468,39 @@ static void conexant_free(struct hda_codec *codec) | |||
444 | if (spec->jacks.list) { | 468 | if (spec->jacks.list) { |
445 | struct conexant_jack *jacks = spec->jacks.list; | 469 | struct conexant_jack *jacks = spec->jacks.list; |
446 | int i; | 470 | int i; |
447 | for (i = 0; i < spec->jacks.used; i++) | 471 | for (i = 0; i < spec->jacks.used; i++, jacks++) { |
448 | snd_device_free(codec->bus->card, &jacks[i].jack); | 472 | if (jacks->jack) |
473 | snd_device_free(codec->bus->card, jacks->jack); | ||
474 | } | ||
449 | snd_array_free(&spec->jacks); | 475 | snd_array_free(&spec->jacks); |
450 | } | 476 | } |
451 | #endif | 477 | #endif |
452 | kfree(codec->spec); | 478 | kfree(codec->spec); |
453 | } | 479 | } |
454 | 480 | ||
481 | static struct snd_kcontrol_new cxt_capture_mixers[] = { | ||
482 | { | ||
483 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
484 | .name = "Capture Source", | ||
485 | .info = conexant_mux_enum_info, | ||
486 | .get = conexant_mux_enum_get, | ||
487 | .put = conexant_mux_enum_put | ||
488 | }, | ||
489 | {} | ||
490 | }; | ||
491 | |||
492 | static const char *slave_vols[] = { | ||
493 | "Headphone Playback Volume", | ||
494 | "Speaker Playback Volume", | ||
495 | NULL | ||
496 | }; | ||
497 | |||
498 | static const char *slave_sws[] = { | ||
499 | "Headphone Playback Switch", | ||
500 | "Speaker Playback Switch", | ||
501 | NULL | ||
502 | }; | ||
503 | |||
455 | static int conexant_build_controls(struct hda_codec *codec) | 504 | static int conexant_build_controls(struct hda_codec *codec) |
456 | { | 505 | { |
457 | struct conexant_spec *spec = codec->spec; | 506 | struct conexant_spec *spec = codec->spec; |
@@ -479,6 +528,32 @@ static int conexant_build_controls(struct hda_codec *codec) | |||
479 | if (err < 0) | 528 | if (err < 0) |
480 | return err; | 529 | return err; |
481 | } | 530 | } |
531 | |||
532 | /* if we have no master control, let's create it */ | ||
533 | if (spec->vmaster_nid && | ||
534 | !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) { | ||
535 | unsigned int vmaster_tlv[4]; | ||
536 | snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid, | ||
537 | HDA_OUTPUT, vmaster_tlv); | ||
538 | err = snd_hda_add_vmaster(codec, "Master Playback Volume", | ||
539 | vmaster_tlv, slave_vols); | ||
540 | if (err < 0) | ||
541 | return err; | ||
542 | } | ||
543 | if (spec->vmaster_nid && | ||
544 | !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { | ||
545 | err = snd_hda_add_vmaster(codec, "Master Playback Switch", | ||
546 | NULL, slave_sws); | ||
547 | if (err < 0) | ||
548 | return err; | ||
549 | } | ||
550 | |||
551 | if (spec->input_mux) { | ||
552 | err = snd_hda_add_new_ctls(codec, cxt_capture_mixers); | ||
553 | if (err < 0) | ||
554 | return err; | ||
555 | } | ||
556 | |||
482 | return 0; | 557 | return 0; |
483 | } | 558 | } |
484 | 559 | ||
@@ -710,13 +785,6 @@ static void cxt5045_hp_unsol_event(struct hda_codec *codec, | |||
710 | } | 785 | } |
711 | 786 | ||
712 | static struct snd_kcontrol_new cxt5045_mixers[] = { | 787 | static struct snd_kcontrol_new cxt5045_mixers[] = { |
713 | { | ||
714 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
715 | .name = "Capture Source", | ||
716 | .info = conexant_mux_enum_info, | ||
717 | .get = conexant_mux_enum_get, | ||
718 | .put = conexant_mux_enum_put | ||
719 | }, | ||
720 | HDA_CODEC_VOLUME("Int Mic Capture Volume", 0x1a, 0x01, HDA_INPUT), | 788 | HDA_CODEC_VOLUME("Int Mic Capture Volume", 0x1a, 0x01, HDA_INPUT), |
721 | HDA_CODEC_MUTE("Int Mic Capture Switch", 0x1a, 0x01, HDA_INPUT), | 789 | HDA_CODEC_MUTE("Int Mic Capture Switch", 0x1a, 0x01, HDA_INPUT), |
722 | HDA_CODEC_VOLUME("Ext Mic Capture Volume", 0x1a, 0x02, HDA_INPUT), | 790 | HDA_CODEC_VOLUME("Ext Mic Capture Volume", 0x1a, 0x02, HDA_INPUT), |
@@ -750,13 +818,6 @@ static struct snd_kcontrol_new cxt5045_benq_mixers[] = { | |||
750 | }; | 818 | }; |
751 | 819 | ||
752 | static struct snd_kcontrol_new cxt5045_mixers_hp530[] = { | 820 | static struct snd_kcontrol_new cxt5045_mixers_hp530[] = { |
753 | { | ||
754 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
755 | .name = "Capture Source", | ||
756 | .info = conexant_mux_enum_info, | ||
757 | .get = conexant_mux_enum_get, | ||
758 | .put = conexant_mux_enum_put | ||
759 | }, | ||
760 | HDA_CODEC_VOLUME("Int Mic Capture Volume", 0x1a, 0x02, HDA_INPUT), | 821 | HDA_CODEC_VOLUME("Int Mic Capture Volume", 0x1a, 0x02, HDA_INPUT), |
761 | HDA_CODEC_MUTE("Int Mic Capture Switch", 0x1a, 0x02, HDA_INPUT), | 822 | HDA_CODEC_MUTE("Int Mic Capture Switch", 0x1a, 0x02, HDA_INPUT), |
762 | HDA_CODEC_VOLUME("Ext Mic Capture Volume", 0x1a, 0x01, HDA_INPUT), | 823 | HDA_CODEC_VOLUME("Ext Mic Capture Volume", 0x1a, 0x01, HDA_INPUT), |
@@ -993,15 +1054,9 @@ static const char *cxt5045_models[CXT5045_MODELS] = { | |||
993 | }; | 1054 | }; |
994 | 1055 | ||
995 | static struct snd_pci_quirk cxt5045_cfg_tbl[] = { | 1056 | static struct snd_pci_quirk cxt5045_cfg_tbl[] = { |
996 | SND_PCI_QUIRK(0x103c, 0x30a5, "HP", CXT5045_LAPTOP_HPSENSE), | ||
997 | SND_PCI_QUIRK(0x103c, 0x30b2, "HP DV Series", CXT5045_LAPTOP_HPSENSE), | ||
998 | SND_PCI_QUIRK(0x103c, 0x30b5, "HP DV2120", CXT5045_LAPTOP_HPSENSE), | ||
999 | SND_PCI_QUIRK(0x103c, 0x30b7, "HP DV6000Z", CXT5045_LAPTOP_HPSENSE), | ||
1000 | SND_PCI_QUIRK(0x103c, 0x30bb, "HP DV8000", CXT5045_LAPTOP_HPSENSE), | ||
1001 | SND_PCI_QUIRK(0x103c, 0x30cd, "HP DV Series", CXT5045_LAPTOP_HPSENSE), | ||
1002 | SND_PCI_QUIRK(0x103c, 0x30cf, "HP DV9533EG", CXT5045_LAPTOP_HPSENSE), | ||
1003 | SND_PCI_QUIRK(0x103c, 0x30d5, "HP 530", CXT5045_LAPTOP_HP530), | 1057 | SND_PCI_QUIRK(0x103c, 0x30d5, "HP 530", CXT5045_LAPTOP_HP530), |
1004 | SND_PCI_QUIRK(0x103c, 0x30d9, "HP Spartan", CXT5045_LAPTOP_HPSENSE), | 1058 | SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3000, "HP DV Series", |
1059 | CXT5045_LAPTOP_HPSENSE), | ||
1005 | SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P105", CXT5045_LAPTOP_MICSENSE), | 1060 | SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P105", CXT5045_LAPTOP_MICSENSE), |
1006 | SND_PCI_QUIRK(0x152d, 0x0753, "Benq R55E", CXT5045_BENQ), | 1061 | SND_PCI_QUIRK(0x152d, 0x0753, "Benq R55E", CXT5045_BENQ), |
1007 | SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_LAPTOP_MICSENSE), | 1062 | SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_LAPTOP_MICSENSE), |
@@ -1011,8 +1066,8 @@ static struct snd_pci_quirk cxt5045_cfg_tbl[] = { | |||
1011 | SND_PCI_QUIRK(0x1509, 0x1e40, "FIC", CXT5045_LAPTOP_HPMICSENSE), | 1066 | SND_PCI_QUIRK(0x1509, 0x1e40, "FIC", CXT5045_LAPTOP_HPMICSENSE), |
1012 | SND_PCI_QUIRK(0x1509, 0x2f05, "FIC", CXT5045_LAPTOP_HPMICSENSE), | 1067 | SND_PCI_QUIRK(0x1509, 0x2f05, "FIC", CXT5045_LAPTOP_HPMICSENSE), |
1013 | SND_PCI_QUIRK(0x1509, 0x2f06, "FIC", CXT5045_LAPTOP_HPMICSENSE), | 1068 | SND_PCI_QUIRK(0x1509, 0x2f06, "FIC", CXT5045_LAPTOP_HPMICSENSE), |
1014 | SND_PCI_QUIRK(0x1631, 0xc106, "Packard Bell", CXT5045_LAPTOP_HPMICSENSE), | 1069 | SND_PCI_QUIRK_MASK(0x1631, 0xff00, 0xc100, "Packard Bell", |
1015 | SND_PCI_QUIRK(0x1631, 0xc107, "Packard Bell", CXT5045_LAPTOP_HPMICSENSE), | 1070 | CXT5045_LAPTOP_HPMICSENSE), |
1016 | SND_PCI_QUIRK(0x8086, 0x2111, "Conexant Reference board", CXT5045_LAPTOP_HPSENSE), | 1071 | SND_PCI_QUIRK(0x8086, 0x2111, "Conexant Reference board", CXT5045_LAPTOP_HPSENSE), |
1017 | {} | 1072 | {} |
1018 | }; | 1073 | }; |
@@ -1026,6 +1081,7 @@ static int patch_cxt5045(struct hda_codec *codec) | |||
1026 | if (!spec) | 1081 | if (!spec) |
1027 | return -ENOMEM; | 1082 | return -ENOMEM; |
1028 | codec->spec = spec; | 1083 | codec->spec = spec; |
1084 | codec->pin_amp_workaround = 1; | ||
1029 | 1085 | ||
1030 | spec->multiout.max_channels = 2; | 1086 | spec->multiout.max_channels = 2; |
1031 | spec->multiout.num_dacs = ARRAY_SIZE(cxt5045_dac_nids); | 1087 | spec->multiout.num_dacs = ARRAY_SIZE(cxt5045_dac_nids); |
@@ -1125,7 +1181,7 @@ static int patch_cxt5045(struct hda_codec *codec) | |||
1125 | /* Conexant 5047 specific */ | 1181 | /* Conexant 5047 specific */ |
1126 | #define CXT5047_SPDIF_OUT 0x11 | 1182 | #define CXT5047_SPDIF_OUT 0x11 |
1127 | 1183 | ||
1128 | static hda_nid_t cxt5047_dac_nids[2] = { 0x10, 0x1c }; | 1184 | static hda_nid_t cxt5047_dac_nids[1] = { 0x10 }; /* 0x1c */ |
1129 | static hda_nid_t cxt5047_adc_nids[1] = { 0x12 }; | 1185 | static hda_nid_t cxt5047_adc_nids[1] = { 0x12 }; |
1130 | static hda_nid_t cxt5047_capsrc_nids[1] = { 0x1a }; | 1186 | static hda_nid_t cxt5047_capsrc_nids[1] = { 0x1a }; |
1131 | 1187 | ||
@@ -1133,20 +1189,6 @@ static struct hda_channel_mode cxt5047_modes[1] = { | |||
1133 | { 2, NULL }, | 1189 | { 2, NULL }, |
1134 | }; | 1190 | }; |
1135 | 1191 | ||
1136 | static struct hda_input_mux cxt5047_capture_source = { | ||
1137 | .num_items = 1, | ||
1138 | .items = { | ||
1139 | { "Mic", 0x2 }, | ||
1140 | } | ||
1141 | }; | ||
1142 | |||
1143 | static struct hda_input_mux cxt5047_hp_capture_source = { | ||
1144 | .num_items = 1, | ||
1145 | .items = { | ||
1146 | { "ExtMic", 0x2 }, | ||
1147 | } | ||
1148 | }; | ||
1149 | |||
1150 | static struct hda_input_mux cxt5047_toshiba_capture_source = { | 1192 | static struct hda_input_mux cxt5047_toshiba_capture_source = { |
1151 | .num_items = 2, | 1193 | .num_items = 2, |
1152 | .items = { | 1194 | .items = { |
@@ -1170,7 +1212,11 @@ static int cxt5047_hp_master_sw_put(struct snd_kcontrol *kcontrol, | |||
1170 | * the headphone jack | 1212 | * the headphone jack |
1171 | */ | 1213 | */ |
1172 | bits = (!spec->hp_present && spec->cur_eapd) ? 0 : HDA_AMP_MUTE; | 1214 | bits = (!spec->hp_present && spec->cur_eapd) ? 0 : HDA_AMP_MUTE; |
1173 | snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0, | 1215 | /* NOTE: Conexat codec needs the index for *OUTPUT* amp of |
1216 | * pin widgets unlike other codecs. In this case, we need to | ||
1217 | * set index 0x01 for the volume from the mixer amp 0x19. | ||
1218 | */ | ||
1219 | snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0x01, | ||
1174 | HDA_AMP_MUTE, bits); | 1220 | HDA_AMP_MUTE, bits); |
1175 | bits = spec->cur_eapd ? 0 : HDA_AMP_MUTE; | 1221 | bits = spec->cur_eapd ? 0 : HDA_AMP_MUTE; |
1176 | snd_hda_codec_amp_stereo(codec, 0x13, HDA_OUTPUT, 0, | 1222 | snd_hda_codec_amp_stereo(codec, 0x13, HDA_OUTPUT, 0, |
@@ -1178,16 +1224,6 @@ static int cxt5047_hp_master_sw_put(struct snd_kcontrol *kcontrol, | |||
1178 | return 1; | 1224 | return 1; |
1179 | } | 1225 | } |
1180 | 1226 | ||
1181 | /* bind volumes of both NID 0x13 (Headphones) and 0x1d (Speakers) */ | ||
1182 | static struct hda_bind_ctls cxt5047_bind_master_vol = { | ||
1183 | .ops = &snd_hda_bind_vol, | ||
1184 | .values = { | ||
1185 | HDA_COMPOSE_AMP_VAL(0x13, 3, 0, HDA_OUTPUT), | ||
1186 | HDA_COMPOSE_AMP_VAL(0x1d, 3, 0, HDA_OUTPUT), | ||
1187 | 0 | ||
1188 | }, | ||
1189 | }; | ||
1190 | |||
1191 | /* mute internal speaker if HP is plugged */ | 1227 | /* mute internal speaker if HP is plugged */ |
1192 | static void cxt5047_hp_automute(struct hda_codec *codec) | 1228 | static void cxt5047_hp_automute(struct hda_codec *codec) |
1193 | { | 1229 | { |
@@ -1198,27 +1234,8 @@ static void cxt5047_hp_automute(struct hda_codec *codec) | |||
1198 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 1234 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
1199 | 1235 | ||
1200 | bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0; | 1236 | bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0; |
1201 | snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0, | 1237 | /* See the note in cxt5047_hp_master_sw_put */ |
1202 | HDA_AMP_MUTE, bits); | 1238 | snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0x01, |
1203 | /* Mute/Unmute PCM 2 for good measure - some systems need this */ | ||
1204 | snd_hda_codec_amp_stereo(codec, 0x1c, HDA_OUTPUT, 0, | ||
1205 | HDA_AMP_MUTE, bits); | ||
1206 | } | ||
1207 | |||
1208 | /* mute internal speaker if HP is plugged */ | ||
1209 | static void cxt5047_hp2_automute(struct hda_codec *codec) | ||
1210 | { | ||
1211 | struct conexant_spec *spec = codec->spec; | ||
1212 | unsigned int bits; | ||
1213 | |||
1214 | spec->hp_present = snd_hda_codec_read(codec, 0x13, 0, | ||
1215 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
1216 | |||
1217 | bits = spec->hp_present ? HDA_AMP_MUTE : 0; | ||
1218 | snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0, | ||
1219 | HDA_AMP_MUTE, bits); | ||
1220 | /* Mute/Unmute PCM 2 for good measure - some systems need this */ | ||
1221 | snd_hda_codec_amp_stereo(codec, 0x1c, HDA_OUTPUT, 0, | ||
1222 | HDA_AMP_MUTE, bits); | 1239 | HDA_AMP_MUTE, bits); |
1223 | } | 1240 | } |
1224 | 1241 | ||
@@ -1259,55 +1276,14 @@ static void cxt5047_hp_unsol_event(struct hda_codec *codec, | |||
1259 | } | 1276 | } |
1260 | } | 1277 | } |
1261 | 1278 | ||
1262 | /* unsolicited event for HP jack sensing - non-EAPD systems */ | 1279 | static struct snd_kcontrol_new cxt5047_base_mixers[] = { |
1263 | static void cxt5047_hp2_unsol_event(struct hda_codec *codec, | 1280 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x19, 0x02, HDA_INPUT), |
1264 | unsigned int res) | 1281 | HDA_CODEC_MUTE("Mic Playback Switch", 0x19, 0x02, HDA_INPUT), |
1265 | { | 1282 | HDA_CODEC_VOLUME("Mic Boost", 0x1a, 0x0, HDA_OUTPUT), |
1266 | res >>= 26; | ||
1267 | switch (res) { | ||
1268 | case CONEXANT_HP_EVENT: | ||
1269 | cxt5047_hp2_automute(codec); | ||
1270 | break; | ||
1271 | case CONEXANT_MIC_EVENT: | ||
1272 | cxt5047_hp_automic(codec); | ||
1273 | break; | ||
1274 | } | ||
1275 | } | ||
1276 | |||
1277 | static struct snd_kcontrol_new cxt5047_mixers[] = { | ||
1278 | HDA_CODEC_VOLUME("Mic Bypass Capture Volume", 0x19, 0x02, HDA_INPUT), | ||
1279 | HDA_CODEC_MUTE("Mic Bypass Capture Switch", 0x19, 0x02, HDA_INPUT), | ||
1280 | HDA_CODEC_VOLUME("Mic Gain Volume", 0x1a, 0x0, HDA_OUTPUT), | ||
1281 | HDA_CODEC_MUTE("Mic Gain Switch", 0x1a, 0x0, HDA_OUTPUT), | ||
1282 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT), | 1283 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT), |
1283 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT), | 1284 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT), |
1284 | HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT), | 1285 | HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT), |
1285 | HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT), | 1286 | HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT), |
1286 | HDA_CODEC_VOLUME("PCM-2 Volume", 0x1c, 0x00, HDA_OUTPUT), | ||
1287 | HDA_CODEC_MUTE("PCM-2 Switch", 0x1c, 0x00, HDA_OUTPUT), | ||
1288 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x00, HDA_OUTPUT), | ||
1289 | HDA_CODEC_MUTE("Speaker Playback Switch", 0x1d, 0x00, HDA_OUTPUT), | ||
1290 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x13, 0x00, HDA_OUTPUT), | ||
1291 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x13, 0x00, HDA_OUTPUT), | ||
1292 | |||
1293 | {} | ||
1294 | }; | ||
1295 | |||
1296 | static struct snd_kcontrol_new cxt5047_toshiba_mixers[] = { | ||
1297 | { | ||
1298 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1299 | .name = "Capture Source", | ||
1300 | .info = conexant_mux_enum_info, | ||
1301 | .get = conexant_mux_enum_get, | ||
1302 | .put = conexant_mux_enum_put | ||
1303 | }, | ||
1304 | HDA_CODEC_VOLUME("Mic Bypass Capture Volume", 0x19, 0x02, HDA_INPUT), | ||
1305 | HDA_CODEC_MUTE("Mic Bypass Capture Switch", 0x19, 0x02, HDA_INPUT), | ||
1306 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT), | ||
1307 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT), | ||
1308 | HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT), | ||
1309 | HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT), | ||
1310 | HDA_BIND_VOL("Master Playback Volume", &cxt5047_bind_master_vol), | ||
1311 | { | 1287 | { |
1312 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1288 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1313 | .name = "Master Playback Switch", | 1289 | .name = "Master Playback Switch", |
@@ -1320,29 +1296,15 @@ static struct snd_kcontrol_new cxt5047_toshiba_mixers[] = { | |||
1320 | {} | 1296 | {} |
1321 | }; | 1297 | }; |
1322 | 1298 | ||
1323 | static struct snd_kcontrol_new cxt5047_hp_mixers[] = { | 1299 | static struct snd_kcontrol_new cxt5047_hp_spk_mixers[] = { |
1324 | { | 1300 | /* See the note in cxt5047_hp_master_sw_put */ |
1325 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1301 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x01, HDA_OUTPUT), |
1326 | .name = "Capture Source", | 1302 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x13, 0x00, HDA_OUTPUT), |
1327 | .info = conexant_mux_enum_info, | 1303 | {} |
1328 | .get = conexant_mux_enum_get, | 1304 | }; |
1329 | .put = conexant_mux_enum_put | 1305 | |
1330 | }, | 1306 | static struct snd_kcontrol_new cxt5047_hp_only_mixers[] = { |
1331 | HDA_CODEC_VOLUME("Mic Bypass Capture Volume", 0x19, 0x02, HDA_INPUT), | ||
1332 | HDA_CODEC_MUTE("Mic Bypass Capture Switch", 0x19,0x02,HDA_INPUT), | ||
1333 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT), | ||
1334 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT), | ||
1335 | HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT), | ||
1336 | HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT), | ||
1337 | HDA_CODEC_VOLUME("Master Playback Volume", 0x13, 0x00, HDA_OUTPUT), | 1307 | HDA_CODEC_VOLUME("Master Playback Volume", 0x13, 0x00, HDA_OUTPUT), |
1338 | { | ||
1339 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1340 | .name = "Master Playback Switch", | ||
1341 | .info = cxt_eapd_info, | ||
1342 | .get = cxt_eapd_get, | ||
1343 | .put = cxt5047_hp_master_sw_put, | ||
1344 | .private_value = 0x13, | ||
1345 | }, | ||
1346 | { } /* end */ | 1308 | { } /* end */ |
1347 | }; | 1309 | }; |
1348 | 1310 | ||
@@ -1353,8 +1315,8 @@ static struct hda_verb cxt5047_init_verbs[] = { | |||
1353 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 }, | 1315 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 }, |
1354 | /* HP, Speaker */ | 1316 | /* HP, Speaker */ |
1355 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | 1317 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, |
1356 | {0x13, AC_VERB_SET_CONNECT_SEL,0x1}, | 1318 | {0x13, AC_VERB_SET_CONNECT_SEL, 0x0}, /* mixer(0x19) */ |
1357 | {0x1d, AC_VERB_SET_CONNECT_SEL,0x0}, | 1319 | {0x1d, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mixer(0x19) */ |
1358 | /* Record selector: Mic */ | 1320 | /* Record selector: Mic */ |
1359 | {0x12, AC_VERB_SET_CONNECT_SEL,0x03}, | 1321 | {0x12, AC_VERB_SET_CONNECT_SEL,0x03}, |
1360 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, | 1322 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, |
@@ -1374,30 +1336,7 @@ static struct hda_verb cxt5047_init_verbs[] = { | |||
1374 | 1336 | ||
1375 | /* configuration for Toshiba Laptops */ | 1337 | /* configuration for Toshiba Laptops */ |
1376 | static struct hda_verb cxt5047_toshiba_init_verbs[] = { | 1338 | static struct hda_verb cxt5047_toshiba_init_verbs[] = { |
1377 | {0x13, AC_VERB_SET_EAPD_BTLENABLE, 0x0 }, /* default on */ | 1339 | {0x13, AC_VERB_SET_EAPD_BTLENABLE, 0x0}, /* default off */ |
1378 | /* pin sensing on HP and Mic jacks */ | ||
1379 | {0x13, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, | ||
1380 | {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, | ||
1381 | /* Speaker routing */ | ||
1382 | {0x1d, AC_VERB_SET_CONNECT_SEL,0x1}, | ||
1383 | {} | ||
1384 | }; | ||
1385 | |||
1386 | /* configuration for HP Laptops */ | ||
1387 | static struct hda_verb cxt5047_hp_init_verbs[] = { | ||
1388 | /* pin sensing on HP jack */ | ||
1389 | {0x13, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, | ||
1390 | /* 0x13 is actually shared by both HP and speaker; | ||
1391 | * setting the connection to 0 (=0x19) makes the master volume control | ||
1392 | * working mysteriouslly... | ||
1393 | */ | ||
1394 | {0x13, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
1395 | /* Record selector: Ext Mic */ | ||
1396 | {0x12, AC_VERB_SET_CONNECT_SEL,0x03}, | ||
1397 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, | ||
1398 | AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, | ||
1399 | /* Speaker routing */ | ||
1400 | {0x1d, AC_VERB_SET_CONNECT_SEL,0x1}, | ||
1401 | {} | 1340 | {} |
1402 | }; | 1341 | }; |
1403 | 1342 | ||
@@ -1562,10 +1501,9 @@ static const char *cxt5047_models[CXT5047_MODELS] = { | |||
1562 | }; | 1501 | }; |
1563 | 1502 | ||
1564 | static struct snd_pci_quirk cxt5047_cfg_tbl[] = { | 1503 | static struct snd_pci_quirk cxt5047_cfg_tbl[] = { |
1565 | SND_PCI_QUIRK(0x103c, 0x30a0, "HP DV1000", CXT5047_LAPTOP), | ||
1566 | SND_PCI_QUIRK(0x103c, 0x30a5, "HP DV5200T/DV8000T", CXT5047_LAPTOP_HP), | 1504 | SND_PCI_QUIRK(0x103c, 0x30a5, "HP DV5200T/DV8000T", CXT5047_LAPTOP_HP), |
1567 | SND_PCI_QUIRK(0x103c, 0x30b2, "HP DV2000T/DV3000T", CXT5047_LAPTOP), | 1505 | SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3000, "HP DV Series", |
1568 | SND_PCI_QUIRK(0x103c, 0x30b5, "HP DV2000Z", CXT5047_LAPTOP), | 1506 | CXT5047_LAPTOP), |
1569 | SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P100", CXT5047_LAPTOP_EAPD), | 1507 | SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P100", CXT5047_LAPTOP_EAPD), |
1570 | {} | 1508 | {} |
1571 | }; | 1509 | }; |
@@ -1579,6 +1517,7 @@ static int patch_cxt5047(struct hda_codec *codec) | |||
1579 | if (!spec) | 1517 | if (!spec) |
1580 | return -ENOMEM; | 1518 | return -ENOMEM; |
1581 | codec->spec = spec; | 1519 | codec->spec = spec; |
1520 | codec->pin_amp_workaround = 1; | ||
1582 | 1521 | ||
1583 | spec->multiout.max_channels = 2; | 1522 | spec->multiout.max_channels = 2; |
1584 | spec->multiout.num_dacs = ARRAY_SIZE(cxt5047_dac_nids); | 1523 | spec->multiout.num_dacs = ARRAY_SIZE(cxt5047_dac_nids); |
@@ -1587,9 +1526,8 @@ static int patch_cxt5047(struct hda_codec *codec) | |||
1587 | spec->num_adc_nids = 1; | 1526 | spec->num_adc_nids = 1; |
1588 | spec->adc_nids = cxt5047_adc_nids; | 1527 | spec->adc_nids = cxt5047_adc_nids; |
1589 | spec->capsrc_nids = cxt5047_capsrc_nids; | 1528 | spec->capsrc_nids = cxt5047_capsrc_nids; |
1590 | spec->input_mux = &cxt5047_capture_source; | ||
1591 | spec->num_mixers = 1; | 1529 | spec->num_mixers = 1; |
1592 | spec->mixers[0] = cxt5047_mixers; | 1530 | spec->mixers[0] = cxt5047_base_mixers; |
1593 | spec->num_init_verbs = 1; | 1531 | spec->num_init_verbs = 1; |
1594 | spec->init_verbs[0] = cxt5047_init_verbs; | 1532 | spec->init_verbs[0] = cxt5047_init_verbs; |
1595 | spec->spdif_route = 0; | 1533 | spec->spdif_route = 0; |
@@ -1603,21 +1541,22 @@ static int patch_cxt5047(struct hda_codec *codec) | |||
1603 | cxt5047_cfg_tbl); | 1541 | cxt5047_cfg_tbl); |
1604 | switch (board_config) { | 1542 | switch (board_config) { |
1605 | case CXT5047_LAPTOP: | 1543 | case CXT5047_LAPTOP: |
1606 | codec->patch_ops.unsol_event = cxt5047_hp2_unsol_event; | 1544 | spec->num_mixers = 2; |
1545 | spec->mixers[1] = cxt5047_hp_spk_mixers; | ||
1546 | codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; | ||
1607 | break; | 1547 | break; |
1608 | case CXT5047_LAPTOP_HP: | 1548 | case CXT5047_LAPTOP_HP: |
1609 | spec->input_mux = &cxt5047_hp_capture_source; | 1549 | spec->num_mixers = 2; |
1610 | spec->num_init_verbs = 2; | 1550 | spec->mixers[1] = cxt5047_hp_only_mixers; |
1611 | spec->init_verbs[1] = cxt5047_hp_init_verbs; | ||
1612 | spec->mixers[0] = cxt5047_hp_mixers; | ||
1613 | codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; | 1551 | codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; |
1614 | codec->patch_ops.init = cxt5047_hp_init; | 1552 | codec->patch_ops.init = cxt5047_hp_init; |
1615 | break; | 1553 | break; |
1616 | case CXT5047_LAPTOP_EAPD: | 1554 | case CXT5047_LAPTOP_EAPD: |
1617 | spec->input_mux = &cxt5047_toshiba_capture_source; | 1555 | spec->input_mux = &cxt5047_toshiba_capture_source; |
1556 | spec->num_mixers = 2; | ||
1557 | spec->mixers[1] = cxt5047_hp_spk_mixers; | ||
1618 | spec->num_init_verbs = 2; | 1558 | spec->num_init_verbs = 2; |
1619 | spec->init_verbs[1] = cxt5047_toshiba_init_verbs; | 1559 | spec->init_verbs[1] = cxt5047_toshiba_init_verbs; |
1620 | spec->mixers[0] = cxt5047_toshiba_mixers; | ||
1621 | codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; | 1560 | codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; |
1622 | break; | 1561 | break; |
1623 | #ifdef CONFIG_SND_DEBUG | 1562 | #ifdef CONFIG_SND_DEBUG |
@@ -1628,6 +1567,7 @@ static int patch_cxt5047(struct hda_codec *codec) | |||
1628 | codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; | 1567 | codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; |
1629 | #endif | 1568 | #endif |
1630 | } | 1569 | } |
1570 | spec->vmaster_nid = 0x13; | ||
1631 | return 0; | 1571 | return 0; |
1632 | } | 1572 | } |
1633 | 1573 | ||
@@ -1663,8 +1603,11 @@ static int cxt5051_hp_master_sw_put(struct snd_kcontrol *kcontrol, | |||
1663 | /* toggle input of built-in and mic jack appropriately */ | 1603 | /* toggle input of built-in and mic jack appropriately */ |
1664 | static void cxt5051_portb_automic(struct hda_codec *codec) | 1604 | static void cxt5051_portb_automic(struct hda_codec *codec) |
1665 | { | 1605 | { |
1606 | struct conexant_spec *spec = codec->spec; | ||
1666 | unsigned int present; | 1607 | unsigned int present; |
1667 | 1608 | ||
1609 | if (spec->no_auto_mic) | ||
1610 | return; | ||
1668 | present = snd_hda_codec_read(codec, 0x17, 0, | 1611 | present = snd_hda_codec_read(codec, 0x17, 0, |
1669 | AC_VERB_GET_PIN_SENSE, 0) & | 1612 | AC_VERB_GET_PIN_SENSE, 0) & |
1670 | AC_PINSENSE_PRESENCE; | 1613 | AC_PINSENSE_PRESENCE; |
@@ -1680,6 +1623,8 @@ static void cxt5051_portc_automic(struct hda_codec *codec) | |||
1680 | unsigned int present; | 1623 | unsigned int present; |
1681 | hda_nid_t new_adc; | 1624 | hda_nid_t new_adc; |
1682 | 1625 | ||
1626 | if (spec->no_auto_mic) | ||
1627 | return; | ||
1683 | present = snd_hda_codec_read(codec, 0x18, 0, | 1628 | present = snd_hda_codec_read(codec, 0x18, 0, |
1684 | AC_VERB_GET_PIN_SENSE, 0) & | 1629 | AC_VERB_GET_PIN_SENSE, 0) & |
1685 | AC_PINSENSE_PRESENCE; | 1630 | AC_PINSENSE_PRESENCE; |
@@ -1766,6 +1711,22 @@ static struct snd_kcontrol_new cxt5051_hp_mixers[] = { | |||
1766 | {} | 1711 | {} |
1767 | }; | 1712 | }; |
1768 | 1713 | ||
1714 | static struct snd_kcontrol_new cxt5051_hp_dv6736_mixers[] = { | ||
1715 | HDA_CODEC_VOLUME("Mic Volume", 0x14, 0x00, HDA_INPUT), | ||
1716 | HDA_CODEC_MUTE("Mic Switch", 0x14, 0x00, HDA_INPUT), | ||
1717 | HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT), | ||
1718 | { | ||
1719 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1720 | .name = "Master Playback Switch", | ||
1721 | .info = cxt_eapd_info, | ||
1722 | .get = cxt_eapd_get, | ||
1723 | .put = cxt5051_hp_master_sw_put, | ||
1724 | .private_value = 0x1a, | ||
1725 | }, | ||
1726 | |||
1727 | {} | ||
1728 | }; | ||
1729 | |||
1769 | static struct hda_verb cxt5051_init_verbs[] = { | 1730 | static struct hda_verb cxt5051_init_verbs[] = { |
1770 | /* Line in, Mic */ | 1731 | /* Line in, Mic */ |
1771 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, | 1732 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, |
@@ -1796,6 +1757,66 @@ static struct hda_verb cxt5051_init_verbs[] = { | |||
1796 | { } /* end */ | 1757 | { } /* end */ |
1797 | }; | 1758 | }; |
1798 | 1759 | ||
1760 | static struct hda_verb cxt5051_hp_dv6736_init_verbs[] = { | ||
1761 | /* Line in, Mic */ | ||
1762 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, | ||
1763 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1764 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0}, | ||
1765 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0}, | ||
1766 | /* SPK */ | ||
1767 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1768 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1769 | /* HP, Amp */ | ||
1770 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
1771 | {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1772 | /* DAC1 */ | ||
1773 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1774 | /* Record selector: Int mic */ | ||
1775 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44}, | ||
1776 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x1}, | ||
1777 | /* SPDIF route: PCM */ | ||
1778 | {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
1779 | /* EAPD */ | ||
1780 | {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | ||
1781 | {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT}, | ||
1782 | {0x17, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CXT5051_PORTB_EVENT}, | ||
1783 | { } /* end */ | ||
1784 | }; | ||
1785 | |||
1786 | static struct hda_verb cxt5051_lenovo_x200_init_verbs[] = { | ||
1787 | /* Line in, Mic */ | ||
1788 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, | ||
1789 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1790 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, | ||
1791 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1792 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
1793 | {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, | ||
1794 | /* SPK */ | ||
1795 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1796 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1797 | /* HP, Amp */ | ||
1798 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
1799 | {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1800 | /* Docking HP */ | ||
1801 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
1802 | {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1803 | /* DAC1 */ | ||
1804 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1805 | /* Record selector: Int mic */ | ||
1806 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44}, | ||
1807 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44}, | ||
1808 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44}, | ||
1809 | /* SPDIF route: PCM */ | ||
1810 | {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
1811 | /* EAPD */ | ||
1812 | {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | ||
1813 | {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT}, | ||
1814 | {0x17, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CXT5051_PORTB_EVENT}, | ||
1815 | {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CXT5051_PORTC_EVENT}, | ||
1816 | {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT}, | ||
1817 | { } /* end */ | ||
1818 | }; | ||
1819 | |||
1799 | /* initialize jack-sensing, too */ | 1820 | /* initialize jack-sensing, too */ |
1800 | static int cxt5051_init(struct hda_codec *codec) | 1821 | static int cxt5051_init(struct hda_codec *codec) |
1801 | { | 1822 | { |
@@ -1813,18 +1834,24 @@ static int cxt5051_init(struct hda_codec *codec) | |||
1813 | enum { | 1834 | enum { |
1814 | CXT5051_LAPTOP, /* Laptops w/ EAPD support */ | 1835 | CXT5051_LAPTOP, /* Laptops w/ EAPD support */ |
1815 | CXT5051_HP, /* no docking */ | 1836 | CXT5051_HP, /* no docking */ |
1837 | CXT5051_HP_DV6736, /* HP without mic switch */ | ||
1838 | CXT5051_LENOVO_X200, /* Lenovo X200 laptop */ | ||
1816 | CXT5051_MODELS | 1839 | CXT5051_MODELS |
1817 | }; | 1840 | }; |
1818 | 1841 | ||
1819 | static const char *cxt5051_models[CXT5051_MODELS] = { | 1842 | static const char *cxt5051_models[CXT5051_MODELS] = { |
1820 | [CXT5051_LAPTOP] = "laptop", | 1843 | [CXT5051_LAPTOP] = "laptop", |
1821 | [CXT5051_HP] = "hp", | 1844 | [CXT5051_HP] = "hp", |
1845 | [CXT5051_HP_DV6736] = "hp-dv6736", | ||
1846 | [CXT5051_LENOVO_X200] = "lenovo-x200", | ||
1822 | }; | 1847 | }; |
1823 | 1848 | ||
1824 | static struct snd_pci_quirk cxt5051_cfg_tbl[] = { | 1849 | static struct snd_pci_quirk cxt5051_cfg_tbl[] = { |
1850 | SND_PCI_QUIRK(0x103c, 0x30cf, "HP DV6736", CXT5051_HP_DV6736), | ||
1825 | SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board", | 1851 | SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board", |
1826 | CXT5051_LAPTOP), | 1852 | CXT5051_LAPTOP), |
1827 | SND_PCI_QUIRK(0x14f1, 0x5051, "HP Spartan 1.1", CXT5051_HP), | 1853 | SND_PCI_QUIRK(0x14f1, 0x5051, "HP Spartan 1.1", CXT5051_HP), |
1854 | SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo X200", CXT5051_LENOVO_X200), | ||
1828 | {} | 1855 | {} |
1829 | }; | 1856 | }; |
1830 | 1857 | ||
@@ -1837,6 +1864,7 @@ static int patch_cxt5051(struct hda_codec *codec) | |||
1837 | if (!spec) | 1864 | if (!spec) |
1838 | return -ENOMEM; | 1865 | return -ENOMEM; |
1839 | codec->spec = spec; | 1866 | codec->spec = spec; |
1867 | codec->pin_amp_workaround = 1; | ||
1840 | 1868 | ||
1841 | codec->patch_ops = conexant_patch_ops; | 1869 | codec->patch_ops = conexant_patch_ops; |
1842 | codec->patch_ops.init = cxt5051_init; | 1870 | codec->patch_ops.init = cxt5051_init; |
@@ -1857,17 +1885,22 @@ static int patch_cxt5051(struct hda_codec *codec) | |||
1857 | spec->cur_adc = 0; | 1885 | spec->cur_adc = 0; |
1858 | spec->cur_adc_idx = 0; | 1886 | spec->cur_adc_idx = 0; |
1859 | 1887 | ||
1888 | codec->patch_ops.unsol_event = cxt5051_hp_unsol_event; | ||
1889 | |||
1860 | board_config = snd_hda_check_board_config(codec, CXT5051_MODELS, | 1890 | board_config = snd_hda_check_board_config(codec, CXT5051_MODELS, |
1861 | cxt5051_models, | 1891 | cxt5051_models, |
1862 | cxt5051_cfg_tbl); | 1892 | cxt5051_cfg_tbl); |
1863 | switch (board_config) { | 1893 | switch (board_config) { |
1864 | case CXT5051_HP: | 1894 | case CXT5051_HP: |
1865 | codec->patch_ops.unsol_event = cxt5051_hp_unsol_event; | ||
1866 | spec->mixers[0] = cxt5051_hp_mixers; | 1895 | spec->mixers[0] = cxt5051_hp_mixers; |
1867 | break; | 1896 | break; |
1868 | default: | 1897 | case CXT5051_HP_DV6736: |
1869 | case CXT5051_LAPTOP: | 1898 | spec->init_verbs[0] = cxt5051_hp_dv6736_init_verbs; |
1870 | codec->patch_ops.unsol_event = cxt5051_hp_unsol_event; | 1899 | spec->mixers[0] = cxt5051_hp_dv6736_mixers; |
1900 | spec->no_auto_mic = 1; | ||
1901 | break; | ||
1902 | case CXT5051_LENOVO_X200: | ||
1903 | spec->init_verbs[0] = cxt5051_lenovo_x200_init_verbs; | ||
1871 | break; | 1904 | break; |
1872 | } | 1905 | } |
1873 | 1906 | ||