diff options
| -rw-r--r-- | sound/pci/hda/patch_conexant.c | 114 | ||||
| -rw-r--r-- | sound/pci/hda/patch_realtek.c | 3 |
2 files changed, 113 insertions, 4 deletions
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index b20e1cede00b..75de40aaab0a 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
| @@ -25,6 +25,8 @@ | |||
| 25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
| 26 | #include <linux/pci.h> | 26 | #include <linux/pci.h> |
| 27 | #include <sound/core.h> | 27 | #include <sound/core.h> |
| 28 | #include <sound/jack.h> | ||
| 29 | |||
| 28 | #include "hda_codec.h" | 30 | #include "hda_codec.h" |
| 29 | #include "hda_local.h" | 31 | #include "hda_local.h" |
| 30 | 32 | ||
| @@ -37,8 +39,21 @@ | |||
| 37 | #define CONEXANT_HP_EVENT 0x37 | 39 | #define CONEXANT_HP_EVENT 0x37 |
| 38 | #define CONEXANT_MIC_EVENT 0x38 | 40 | #define CONEXANT_MIC_EVENT 0x38 |
| 39 | 41 | ||
| 42 | /* Conexant 5051 specific */ | ||
| 43 | |||
| 44 | #define CXT5051_SPDIF_OUT 0x1C | ||
| 45 | #define CXT5051_PORTB_EVENT 0x38 | ||
| 46 | #define CXT5051_PORTC_EVENT 0x39 | ||
| 40 | 47 | ||
| 41 | 48 | ||
| 49 | struct conexant_jack { | ||
| 50 | |||
| 51 | hda_nid_t nid; | ||
| 52 | int type; | ||
| 53 | struct snd_jack *jack; | ||
| 54 | |||
| 55 | }; | ||
| 56 | |||
| 42 | struct conexant_spec { | 57 | struct conexant_spec { |
| 43 | 58 | ||
| 44 | struct snd_kcontrol_new *mixers[5]; | 59 | struct snd_kcontrol_new *mixers[5]; |
| @@ -83,6 +98,9 @@ struct conexant_spec { | |||
| 83 | 98 | ||
| 84 | unsigned int spdif_route; | 99 | unsigned int spdif_route; |
| 85 | 100 | ||
| 101 | /* jack detection */ | ||
| 102 | struct snd_array jacks; | ||
| 103 | |||
| 86 | /* dynamic controls, init_verbs and input_mux */ | 104 | /* dynamic controls, init_verbs and input_mux */ |
| 87 | struct auto_pin_cfg autocfg; | 105 | struct auto_pin_cfg autocfg; |
| 88 | struct hda_input_mux private_imux; | 106 | struct hda_input_mux private_imux; |
| @@ -329,6 +347,86 @@ static int conexant_mux_enum_put(struct snd_kcontrol *kcontrol, | |||
| 329 | &spec->cur_mux[adc_idx]); | 347 | &spec->cur_mux[adc_idx]); |
| 330 | } | 348 | } |
| 331 | 349 | ||
| 350 | static int conexant_add_jack(struct hda_codec *codec, | ||
| 351 | hda_nid_t nid, int type) | ||
| 352 | { | ||
| 353 | struct conexant_spec *spec; | ||
| 354 | struct conexant_jack *jack; | ||
| 355 | const char *name; | ||
| 356 | |||
| 357 | spec = codec->spec; | ||
| 358 | snd_array_init(&spec->jacks, sizeof(*jack), 32); | ||
| 359 | jack = snd_array_new(&spec->jacks); | ||
| 360 | name = (type == SND_JACK_HEADPHONE) ? "Headphone" : "Mic" ; | ||
| 361 | |||
| 362 | if (!jack) | ||
| 363 | return -ENOMEM; | ||
| 364 | |||
| 365 | jack->nid = nid; | ||
| 366 | jack->type = type; | ||
| 367 | |||
| 368 | return snd_jack_new(codec->bus->card, name, type, &jack->jack); | ||
| 369 | } | ||
| 370 | |||
| 371 | static void conexant_report_jack(struct hda_codec *codec, hda_nid_t nid) | ||
| 372 | { | ||
| 373 | struct conexant_spec *spec = codec->spec; | ||
| 374 | struct conexant_jack *jacks = spec->jacks.list; | ||
| 375 | |||
| 376 | if (jacks) { | ||
| 377 | int i; | ||
| 378 | for (i = 0; i < spec->jacks.used; i++) { | ||
| 379 | if (jacks->nid == nid) { | ||
| 380 | unsigned int present; | ||
| 381 | present = snd_hda_codec_read(codec, nid, 0, | ||
| 382 | AC_VERB_GET_PIN_SENSE, 0) & | ||
| 383 | AC_PINSENSE_PRESENCE; | ||
| 384 | |||
| 385 | present = (present) ? jacks->type : 0 ; | ||
| 386 | |||
| 387 | snd_jack_report(jacks->jack, | ||
| 388 | present); | ||
| 389 | } | ||
| 390 | jacks++; | ||
| 391 | } | ||
| 392 | } | ||
| 393 | } | ||
| 394 | |||
| 395 | static int conexant_init_jacks(struct hda_codec *codec) | ||
| 396 | { | ||
| 397 | #ifdef CONFIG_SND_JACK | ||
| 398 | struct conexant_spec *spec = codec->spec; | ||
| 399 | int i; | ||
| 400 | |||
| 401 | for (i = 0; i < spec->num_init_verbs; i++) { | ||
| 402 | const struct hda_verb *hv; | ||
| 403 | |||
| 404 | hv = spec->init_verbs[i]; | ||
| 405 | while (hv->nid) { | ||
| 406 | int err = 0; | ||
| 407 | switch (hv->param ^ AC_USRSP_EN) { | ||
| 408 | case CONEXANT_HP_EVENT: | ||
| 409 | err = conexant_add_jack(codec, hv->nid, | ||
| 410 | SND_JACK_HEADPHONE); | ||
| 411 | conexant_report_jack(codec, hv->nid); | ||
| 412 | break; | ||
| 413 | case CXT5051_PORTC_EVENT: | ||
| 414 | case CONEXANT_MIC_EVENT: | ||
| 415 | err = conexant_add_jack(codec, hv->nid, | ||
| 416 | SND_JACK_MICROPHONE); | ||
| 417 | conexant_report_jack(codec, hv->nid); | ||
| 418 | break; | ||
| 419 | } | ||
| 420 | if (err < 0) | ||
| 421 | return err; | ||
| 422 | ++hv; | ||
| 423 | } | ||
| 424 | } | ||
| 425 | #endif | ||
| 426 | return 0; | ||
| 427 | |||
| 428 | } | ||
| 429 | |||
| 332 | static int conexant_init(struct hda_codec *codec) | 430 | static int conexant_init(struct hda_codec *codec) |
| 333 | { | 431 | { |
| 334 | struct conexant_spec *spec = codec->spec; | 432 | struct conexant_spec *spec = codec->spec; |
| @@ -341,6 +439,16 @@ static int conexant_init(struct hda_codec *codec) | |||
| 341 | 439 | ||
| 342 | static void conexant_free(struct hda_codec *codec) | 440 | static void conexant_free(struct hda_codec *codec) |
| 343 | { | 441 | { |
| 442 | #ifdef CONFIG_SND_JACK | ||
| 443 | struct conexant_spec *spec = codec->spec; | ||
| 444 | if (spec->jacks.list) { | ||
| 445 | struct conexant_jack *jacks = spec->jacks.list; | ||
| 446 | int i; | ||
| 447 | for (i = 0; i < spec->jacks.used; i++) | ||
| 448 | snd_device_free(codec->bus->card, &jacks[i].jack); | ||
| 449 | snd_array_free(&spec->jacks); | ||
| 450 | } | ||
| 451 | #endif | ||
| 344 | kfree(codec->spec); | 452 | kfree(codec->spec); |
| 345 | } | 453 | } |
| 346 | 454 | ||
| @@ -1526,9 +1634,6 @@ static int patch_cxt5047(struct hda_codec *codec) | |||
| 1526 | /* Conexant 5051 specific */ | 1634 | /* Conexant 5051 specific */ |
| 1527 | static hda_nid_t cxt5051_dac_nids[1] = { 0x10 }; | 1635 | static hda_nid_t cxt5051_dac_nids[1] = { 0x10 }; |
| 1528 | static hda_nid_t cxt5051_adc_nids[2] = { 0x14, 0x15 }; | 1636 | static hda_nid_t cxt5051_adc_nids[2] = { 0x14, 0x15 }; |
| 1529 | #define CXT5051_SPDIF_OUT 0x1C | ||
| 1530 | #define CXT5051_PORTB_EVENT 0x38 | ||
| 1531 | #define CXT5051_PORTC_EVENT 0x39 | ||
| 1532 | 1637 | ||
| 1533 | static struct hda_channel_mode cxt5051_modes[1] = { | 1638 | static struct hda_channel_mode cxt5051_modes[1] = { |
| 1534 | { 2, NULL }, | 1639 | { 2, NULL }, |
| @@ -1608,6 +1713,7 @@ static void cxt5051_hp_automute(struct hda_codec *codec) | |||
| 1608 | static void cxt5051_hp_unsol_event(struct hda_codec *codec, | 1713 | static void cxt5051_hp_unsol_event(struct hda_codec *codec, |
| 1609 | unsigned int res) | 1714 | unsigned int res) |
| 1610 | { | 1715 | { |
| 1716 | int nid = (res & AC_UNSOL_RES_SUBTAG) >> 20; | ||
| 1611 | switch (res >> 26) { | 1717 | switch (res >> 26) { |
| 1612 | case CONEXANT_HP_EVENT: | 1718 | case CONEXANT_HP_EVENT: |
| 1613 | cxt5051_hp_automute(codec); | 1719 | cxt5051_hp_automute(codec); |
| @@ -1619,6 +1725,7 @@ static void cxt5051_hp_unsol_event(struct hda_codec *codec, | |||
| 1619 | cxt5051_portc_automic(codec); | 1725 | cxt5051_portc_automic(codec); |
| 1620 | break; | 1726 | break; |
| 1621 | } | 1727 | } |
| 1728 | conexant_report_jack(codec, nid); | ||
| 1622 | } | 1729 | } |
| 1623 | 1730 | ||
| 1624 | static struct snd_kcontrol_new cxt5051_mixers[] = { | 1731 | static struct snd_kcontrol_new cxt5051_mixers[] = { |
| @@ -1693,6 +1800,7 @@ static struct hda_verb cxt5051_init_verbs[] = { | |||
| 1693 | static int cxt5051_init(struct hda_codec *codec) | 1800 | static int cxt5051_init(struct hda_codec *codec) |
| 1694 | { | 1801 | { |
| 1695 | conexant_init(codec); | 1802 | conexant_init(codec); |
| 1803 | conexant_init_jacks(codec); | ||
| 1696 | if (codec->patch_ops.unsol_event) { | 1804 | if (codec->patch_ops.unsol_event) { |
| 1697 | cxt5051_hp_automute(codec); | 1805 | cxt5051_hp_automute(codec); |
| 1698 | cxt5051_portb_automic(codec); | 1806 | cxt5051_portb_automic(codec); |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 0bd4e6bf354d..9065ebf9c065 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
| @@ -8467,6 +8467,7 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { | |||
| 8467 | SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP), | 8467 | SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP), |
| 8468 | SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_3ST_HP), | 8468 | SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_3ST_HP), |
| 8469 | SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC883_6ST_DIG), | 8469 | SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC883_6ST_DIG), |
| 8470 | SND_PCI_QUIRK(0x103c, 0x2a66, "HP Acacia", ALC888_3ST_HP), | ||
| 8470 | SND_PCI_QUIRK(0x1043, 0x1873, "Asus M90V", ALC888_ASUS_M90V), | 8471 | SND_PCI_QUIRK(0x1043, 0x1873, "Asus M90V", ALC888_ASUS_M90V), |
| 8471 | SND_PCI_QUIRK(0x1043, 0x8249, "Asus M2A-VM HDMI", ALC883_3ST_6ch_DIG), | 8472 | SND_PCI_QUIRK(0x1043, 0x8249, "Asus M2A-VM HDMI", ALC883_3ST_6ch_DIG), |
| 8472 | SND_PCI_QUIRK(0x1043, 0x82fe, "Asus P5Q-EM HDMI", ALC1200_ASUS_P5Q), | 8473 | SND_PCI_QUIRK(0x1043, 0x82fe, "Asus P5Q-EM HDMI", ALC1200_ASUS_P5Q), |
| @@ -16638,9 +16639,9 @@ static struct hda_codec_preset snd_hda_preset_realtek[] = { | |||
| 16638 | .patch = patch_alc882 }, /* should be patch_alc883() in future */ | 16639 | .patch = patch_alc882 }, /* should be patch_alc883() in future */ |
| 16639 | { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 }, | 16640 | { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 }, |
| 16640 | { .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc883 }, | 16641 | { .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc883 }, |
| 16641 | { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc883 }, | ||
| 16642 | { .id = 0x10ec0888, .rev = 0x100101, .name = "ALC1200", | 16642 | { .id = 0x10ec0888, .rev = 0x100101, .name = "ALC1200", |
| 16643 | .patch = patch_alc883 }, | 16643 | .patch = patch_alc883 }, |
| 16644 | { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc883 }, | ||
| 16644 | { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc883 }, | 16645 | { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc883 }, |
| 16645 | {} /* terminator */ | 16646 | {} /* terminator */ |
| 16646 | }; | 16647 | }; |
