aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/pci/hda/patch_conexant.c114
-rw-r--r--sound/pci/hda/patch_realtek.c3
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
49struct conexant_jack {
50
51 hda_nid_t nid;
52 int type;
53 struct snd_jack *jack;
54
55};
56
42struct conexant_spec { 57struct 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
350static 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
371static 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
395static 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
332static int conexant_init(struct hda_codec *codec) 430static 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
342static void conexant_free(struct hda_codec *codec) 440static 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 */
1527static hda_nid_t cxt5051_dac_nids[1] = { 0x10 }; 1635static hda_nid_t cxt5051_dac_nids[1] = { 0x10 };
1528static hda_nid_t cxt5051_adc_nids[2] = { 0x14, 0x15 }; 1636static 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
1533static struct hda_channel_mode cxt5051_modes[1] = { 1638static 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)
1608static void cxt5051_hp_unsol_event(struct hda_codec *codec, 1713static 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
1624static struct snd_kcontrol_new cxt5051_mixers[] = { 1731static struct snd_kcontrol_new cxt5051_mixers[] = {
@@ -1693,6 +1800,7 @@ static struct hda_verb cxt5051_init_verbs[] = {
1693static int cxt5051_init(struct hda_codec *codec) 1800static 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};