mirror of https://gitee.com/openkylin/linux.git
Merge branch 'topic/hda' into for-linus
This commit is contained in:
commit
8924c671b6
|
@ -25,6 +25,8 @@
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
#include <sound/core.h>
|
#include <sound/core.h>
|
||||||
|
#include <sound/jack.h>
|
||||||
|
|
||||||
#include "hda_codec.h"
|
#include "hda_codec.h"
|
||||||
#include "hda_local.h"
|
#include "hda_local.h"
|
||||||
|
|
||||||
|
@ -37,7 +39,20 @@
|
||||||
#define CONEXANT_HP_EVENT 0x37
|
#define CONEXANT_HP_EVENT 0x37
|
||||||
#define CONEXANT_MIC_EVENT 0x38
|
#define CONEXANT_MIC_EVENT 0x38
|
||||||
|
|
||||||
|
/* Conexant 5051 specific */
|
||||||
|
|
||||||
|
#define CXT5051_SPDIF_OUT 0x1C
|
||||||
|
#define CXT5051_PORTB_EVENT 0x38
|
||||||
|
#define CXT5051_PORTC_EVENT 0x39
|
||||||
|
|
||||||
|
|
||||||
|
struct conexant_jack {
|
||||||
|
|
||||||
|
hda_nid_t nid;
|
||||||
|
int type;
|
||||||
|
struct snd_jack *jack;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
struct conexant_spec {
|
struct conexant_spec {
|
||||||
|
|
||||||
|
@ -83,6 +98,9 @@ struct conexant_spec {
|
||||||
|
|
||||||
unsigned int spdif_route;
|
unsigned int spdif_route;
|
||||||
|
|
||||||
|
/* jack detection */
|
||||||
|
struct snd_array jacks;
|
||||||
|
|
||||||
/* dynamic controls, init_verbs and input_mux */
|
/* dynamic controls, init_verbs and input_mux */
|
||||||
struct auto_pin_cfg autocfg;
|
struct auto_pin_cfg autocfg;
|
||||||
struct hda_input_mux private_imux;
|
struct hda_input_mux private_imux;
|
||||||
|
@ -329,6 +347,86 @@ static int conexant_mux_enum_put(struct snd_kcontrol *kcontrol,
|
||||||
&spec->cur_mux[adc_idx]);
|
&spec->cur_mux[adc_idx]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int conexant_add_jack(struct hda_codec *codec,
|
||||||
|
hda_nid_t nid, int type)
|
||||||
|
{
|
||||||
|
struct conexant_spec *spec;
|
||||||
|
struct conexant_jack *jack;
|
||||||
|
const char *name;
|
||||||
|
|
||||||
|
spec = codec->spec;
|
||||||
|
snd_array_init(&spec->jacks, sizeof(*jack), 32);
|
||||||
|
jack = snd_array_new(&spec->jacks);
|
||||||
|
name = (type == SND_JACK_HEADPHONE) ? "Headphone" : "Mic" ;
|
||||||
|
|
||||||
|
if (!jack)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
jack->nid = nid;
|
||||||
|
jack->type = type;
|
||||||
|
|
||||||
|
return snd_jack_new(codec->bus->card, name, type, &jack->jack);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void conexant_report_jack(struct hda_codec *codec, hda_nid_t nid)
|
||||||
|
{
|
||||||
|
struct conexant_spec *spec = codec->spec;
|
||||||
|
struct conexant_jack *jacks = spec->jacks.list;
|
||||||
|
|
||||||
|
if (jacks) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < spec->jacks.used; i++) {
|
||||||
|
if (jacks->nid == nid) {
|
||||||
|
unsigned int present;
|
||||||
|
present = snd_hda_codec_read(codec, nid, 0,
|
||||||
|
AC_VERB_GET_PIN_SENSE, 0) &
|
||||||
|
AC_PINSENSE_PRESENCE;
|
||||||
|
|
||||||
|
present = (present) ? jacks->type : 0 ;
|
||||||
|
|
||||||
|
snd_jack_report(jacks->jack,
|
||||||
|
present);
|
||||||
|
}
|
||||||
|
jacks++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int conexant_init_jacks(struct hda_codec *codec)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_SND_JACK
|
||||||
|
struct conexant_spec *spec = codec->spec;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < spec->num_init_verbs; i++) {
|
||||||
|
const struct hda_verb *hv;
|
||||||
|
|
||||||
|
hv = spec->init_verbs[i];
|
||||||
|
while (hv->nid) {
|
||||||
|
int err = 0;
|
||||||
|
switch (hv->param ^ AC_USRSP_EN) {
|
||||||
|
case CONEXANT_HP_EVENT:
|
||||||
|
err = conexant_add_jack(codec, hv->nid,
|
||||||
|
SND_JACK_HEADPHONE);
|
||||||
|
conexant_report_jack(codec, hv->nid);
|
||||||
|
break;
|
||||||
|
case CXT5051_PORTC_EVENT:
|
||||||
|
case CONEXANT_MIC_EVENT:
|
||||||
|
err = conexant_add_jack(codec, hv->nid,
|
||||||
|
SND_JACK_MICROPHONE);
|
||||||
|
conexant_report_jack(codec, hv->nid);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
++hv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static int conexant_init(struct hda_codec *codec)
|
static int conexant_init(struct hda_codec *codec)
|
||||||
{
|
{
|
||||||
struct conexant_spec *spec = codec->spec;
|
struct conexant_spec *spec = codec->spec;
|
||||||
|
@ -341,6 +439,16 @@ static int conexant_init(struct hda_codec *codec)
|
||||||
|
|
||||||
static void conexant_free(struct hda_codec *codec)
|
static void conexant_free(struct hda_codec *codec)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_SND_JACK
|
||||||
|
struct conexant_spec *spec = codec->spec;
|
||||||
|
if (spec->jacks.list) {
|
||||||
|
struct conexant_jack *jacks = spec->jacks.list;
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < spec->jacks.used; i++)
|
||||||
|
snd_device_free(codec->bus->card, &jacks[i].jack);
|
||||||
|
snd_array_free(&spec->jacks);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
kfree(codec->spec);
|
kfree(codec->spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1526,9 +1634,6 @@ static int patch_cxt5047(struct hda_codec *codec)
|
||||||
/* Conexant 5051 specific */
|
/* Conexant 5051 specific */
|
||||||
static hda_nid_t cxt5051_dac_nids[1] = { 0x10 };
|
static hda_nid_t cxt5051_dac_nids[1] = { 0x10 };
|
||||||
static hda_nid_t cxt5051_adc_nids[2] = { 0x14, 0x15 };
|
static hda_nid_t cxt5051_adc_nids[2] = { 0x14, 0x15 };
|
||||||
#define CXT5051_SPDIF_OUT 0x1C
|
|
||||||
#define CXT5051_PORTB_EVENT 0x38
|
|
||||||
#define CXT5051_PORTC_EVENT 0x39
|
|
||||||
|
|
||||||
static struct hda_channel_mode cxt5051_modes[1] = {
|
static struct hda_channel_mode cxt5051_modes[1] = {
|
||||||
{ 2, NULL },
|
{ 2, NULL },
|
||||||
|
@ -1608,6 +1713,7 @@ static void cxt5051_hp_automute(struct hda_codec *codec)
|
||||||
static void cxt5051_hp_unsol_event(struct hda_codec *codec,
|
static void cxt5051_hp_unsol_event(struct hda_codec *codec,
|
||||||
unsigned int res)
|
unsigned int res)
|
||||||
{
|
{
|
||||||
|
int nid = (res & AC_UNSOL_RES_SUBTAG) >> 20;
|
||||||
switch (res >> 26) {
|
switch (res >> 26) {
|
||||||
case CONEXANT_HP_EVENT:
|
case CONEXANT_HP_EVENT:
|
||||||
cxt5051_hp_automute(codec);
|
cxt5051_hp_automute(codec);
|
||||||
|
@ -1619,6 +1725,7 @@ static void cxt5051_hp_unsol_event(struct hda_codec *codec,
|
||||||
cxt5051_portc_automic(codec);
|
cxt5051_portc_automic(codec);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
conexant_report_jack(codec, nid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct snd_kcontrol_new cxt5051_mixers[] = {
|
static struct snd_kcontrol_new cxt5051_mixers[] = {
|
||||||
|
@ -1693,6 +1800,7 @@ static struct hda_verb cxt5051_init_verbs[] = {
|
||||||
static int cxt5051_init(struct hda_codec *codec)
|
static int cxt5051_init(struct hda_codec *codec)
|
||||||
{
|
{
|
||||||
conexant_init(codec);
|
conexant_init(codec);
|
||||||
|
conexant_init_jacks(codec);
|
||||||
if (codec->patch_ops.unsol_event) {
|
if (codec->patch_ops.unsol_event) {
|
||||||
cxt5051_hp_automute(codec);
|
cxt5051_hp_automute(codec);
|
||||||
cxt5051_portb_automic(codec);
|
cxt5051_portb_automic(codec);
|
||||||
|
|
|
@ -8467,6 +8467,7 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
|
||||||
SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP),
|
SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP),
|
||||||
SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_3ST_HP),
|
SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_3ST_HP),
|
||||||
SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC883_6ST_DIG),
|
SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC883_6ST_DIG),
|
||||||
|
SND_PCI_QUIRK(0x103c, 0x2a66, "HP Acacia", ALC888_3ST_HP),
|
||||||
SND_PCI_QUIRK(0x1043, 0x1873, "Asus M90V", ALC888_ASUS_M90V),
|
SND_PCI_QUIRK(0x1043, 0x1873, "Asus M90V", ALC888_ASUS_M90V),
|
||||||
SND_PCI_QUIRK(0x1043, 0x8249, "Asus M2A-VM HDMI", ALC883_3ST_6ch_DIG),
|
SND_PCI_QUIRK(0x1043, 0x8249, "Asus M2A-VM HDMI", ALC883_3ST_6ch_DIG),
|
||||||
SND_PCI_QUIRK(0x1043, 0x82fe, "Asus P5Q-EM HDMI", ALC1200_ASUS_P5Q),
|
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[] = {
|
||||||
.patch = patch_alc882 }, /* should be patch_alc883() in future */
|
.patch = patch_alc882 }, /* should be patch_alc883() in future */
|
||||||
{ .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
|
{ .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
|
||||||
{ .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc883 },
|
{ .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc883 },
|
||||||
{ .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc883 },
|
|
||||||
{ .id = 0x10ec0888, .rev = 0x100101, .name = "ALC1200",
|
{ .id = 0x10ec0888, .rev = 0x100101, .name = "ALC1200",
|
||||||
.patch = patch_alc883 },
|
.patch = patch_alc883 },
|
||||||
|
{ .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc883 },
|
||||||
{ .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc883 },
|
{ .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc883 },
|
||||||
{} /* terminator */
|
{} /* terminator */
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue