Commit da691064 authored by Takashi Iwai's avatar Takashi Iwai

Merge branch 'fix/hda' into topic/hda

parents 68ef0561 2f451d2a
...@@ -52,6 +52,7 @@ struct link_slave { ...@@ -52,6 +52,7 @@ struct link_slave {
struct link_ctl_info info; struct link_ctl_info info;
int vals[2]; /* current values */ int vals[2]; /* current values */
unsigned int flags; unsigned int flags;
struct snd_kcontrol *kctl; /* original kcontrol pointer */
struct snd_kcontrol slave; /* the copy of original control entry */ struct snd_kcontrol slave; /* the copy of original control entry */
}; };
...@@ -252,6 +253,7 @@ int _snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave, ...@@ -252,6 +253,7 @@ int _snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave,
slave->count * sizeof(*slave->vd), GFP_KERNEL); slave->count * sizeof(*slave->vd), GFP_KERNEL);
if (!srec) if (!srec)
return -ENOMEM; return -ENOMEM;
srec->kctl = slave;
srec->slave = *slave; srec->slave = *slave;
memcpy(srec->slave.vd, slave->vd, slave->count * sizeof(*slave->vd)); memcpy(srec->slave.vd, slave->vd, slave->count * sizeof(*slave->vd));
srec->master = master_link; srec->master = master_link;
...@@ -333,10 +335,18 @@ static int master_put(struct snd_kcontrol *kcontrol, ...@@ -333,10 +335,18 @@ static int master_put(struct snd_kcontrol *kcontrol,
static void master_free(struct snd_kcontrol *kcontrol) static void master_free(struct snd_kcontrol *kcontrol)
{ {
struct link_master *master = snd_kcontrol_chip(kcontrol); struct link_master *master = snd_kcontrol_chip(kcontrol);
struct link_slave *slave; struct link_slave *slave, *n;
list_for_each_entry(slave, &master->slaves, list) /* free all slave links and retore the original slave kctls */
slave->master = NULL; list_for_each_entry_safe(slave, n, &master->slaves, list) {
struct snd_kcontrol *sctl = slave->kctl;
struct list_head olist = sctl->list;
memcpy(sctl, &slave->slave, sizeof(*sctl));
memcpy(sctl->vd, slave->slave.vd,
sctl->count * sizeof(*sctl->vd));
sctl->list = olist; /* keep the current linked-list */
kfree(slave);
}
kfree(master); kfree(master);
} }
......
...@@ -2331,6 +2331,39 @@ int snd_hda_codec_reset(struct hda_codec *codec) ...@@ -2331,6 +2331,39 @@ int snd_hda_codec_reset(struct hda_codec *codec)
return 0; return 0;
} }
typedef int (*map_slave_func_t)(void *, struct snd_kcontrol *);
/* apply the function to all matching slave ctls in the mixer list */
static int map_slaves(struct hda_codec *codec, const char * const *slaves,
map_slave_func_t func, void *data)
{
struct hda_nid_item *items;
const char * const *s;
int i, err;
items = codec->mixers.list;
for (i = 0; i < codec->mixers.used; i++) {
struct snd_kcontrol *sctl = items[i].kctl;
if (!sctl || !sctl->id.name ||
sctl->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER)
continue;
for (s = slaves; *s; s++) {
if (!strcmp(sctl->id.name, *s)) {
err = func(data, sctl);
if (err)
return err;
break;
}
}
}
return 0;
}
static int check_slave_present(void *data, struct snd_kcontrol *sctl)
{
return 1;
}
/** /**
* snd_hda_add_vmaster - create a virtual master control and add slaves * snd_hda_add_vmaster - create a virtual master control and add slaves
* @codec: HD-audio codec * @codec: HD-audio codec
...@@ -2351,12 +2384,10 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name, ...@@ -2351,12 +2384,10 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
unsigned int *tlv, const char * const *slaves) unsigned int *tlv, const char * const *slaves)
{ {
struct snd_kcontrol *kctl; struct snd_kcontrol *kctl;
const char * const *s;
int err; int err;
for (s = slaves; *s && !snd_hda_find_mixer_ctl(codec, *s); s++) err = map_slaves(codec, slaves, check_slave_present, NULL);
; if (err != 1) {
if (!*s) {
snd_printdd("No slave found for %s\n", name); snd_printdd("No slave found for %s\n", name);
return 0; return 0;
} }
...@@ -2367,23 +2398,10 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name, ...@@ -2367,23 +2398,10 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
if (err < 0) if (err < 0)
return err; return err;
for (s = slaves; *s; s++) { err = map_slaves(codec, slaves, (map_slave_func_t)snd_ctl_add_slave,
struct snd_kcontrol *sctl; kctl);
int i = 0; if (err < 0)
for (;;) { return err;
sctl = _snd_hda_find_mixer_ctl(codec, *s, i);
if (!sctl) {
if (!i)
snd_printdd("Cannot find slave %s, "
"skipped\n", *s);
break;
}
err = snd_ctl_add_slave(kctl, sctl);
if (err < 0)
return err;
i++;
}
}
return 0; return 0;
} }
EXPORT_SYMBOL_HDA(snd_hda_add_vmaster); EXPORT_SYMBOL_HDA(snd_hda_add_vmaster);
...@@ -4752,6 +4770,7 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec, ...@@ -4752,6 +4770,7 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
memset(sequences_hp, 0, sizeof(sequences_hp)); memset(sequences_hp, 0, sizeof(sequences_hp));
assoc_line_out = 0; assoc_line_out = 0;
codec->ignore_misc_bit = true;
end_nid = codec->start_nid + codec->num_nodes; end_nid = codec->start_nid + codec->num_nodes;
for (nid = codec->start_nid; nid < end_nid; nid++) { for (nid = codec->start_nid; nid < end_nid; nid++) {
unsigned int wid_caps = get_wcaps(codec, nid); unsigned int wid_caps = get_wcaps(codec, nid);
...@@ -4767,6 +4786,9 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec, ...@@ -4767,6 +4786,9 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
continue; continue;
def_conf = snd_hda_codec_get_pincfg(codec, nid); def_conf = snd_hda_codec_get_pincfg(codec, nid);
if (!(get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) &
AC_DEFCFG_MISC_NO_PRESENCE))
codec->ignore_misc_bit = false;
conn = get_defcfg_connect(def_conf); conn = get_defcfg_connect(def_conf);
if (conn == AC_JACK_PORT_NONE) if (conn == AC_JACK_PORT_NONE)
continue; continue;
......
...@@ -854,6 +854,7 @@ struct hda_codec { ...@@ -854,6 +854,7 @@ struct hda_codec {
unsigned int no_sticky_stream:1; /* no sticky-PCM stream assignment */ unsigned int no_sticky_stream:1; /* no sticky-PCM stream assignment */
unsigned int pins_shutup:1; /* pins are shut up */ unsigned int pins_shutup:1; /* pins are shut up */
unsigned int no_trigger_sense:1; /* don't trigger at pin-sensing */ unsigned int no_trigger_sense:1; /* don't trigger at pin-sensing */
unsigned int ignore_misc_bit:1; /* ignore MISC_NO_PRESENCE bit */
#ifdef CONFIG_SND_HDA_POWER_SAVE #ifdef CONFIG_SND_HDA_POWER_SAVE
unsigned int power_on :1; /* current (global) power-state */ unsigned int power_on :1; /* current (global) power-state */
unsigned int power_transition :1; /* power-state in transition */ unsigned int power_transition :1; /* power-state in transition */
......
...@@ -510,13 +510,15 @@ int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid); ...@@ -510,13 +510,15 @@ int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid);
static inline bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid) static inline bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid)
{ {
return (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_PRES_DETECT) && if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_PRES_DETECT))
/* disable MISC_NO_PRESENCE check because it may break too return false;
* many devices if (!codec->ignore_misc_bit &&
*/ (get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) &
/*(get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid) & AC_DEFCFG_MISC_NO_PRESENCE))
AC_DEFCFG_MISC_NO_PRESENCE)) &&*/ return false;
(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP); if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP))
return false;
return true;
} }
/* flags for hda_nid_item */ /* flags for hda_nid_item */
......
...@@ -2937,6 +2937,45 @@ static unsigned int sis_codec_bits[3] = { ...@@ -2937,6 +2937,45 @@ static unsigned int sis_codec_bits[3] = {
ICH_PCR, ICH_SCR, ICH_SIS_TCR ICH_PCR, ICH_SCR, ICH_SIS_TCR
}; };
static int __devinit snd_intel8x0_inside_vm(struct pci_dev *pci)
{
int result = inside_vm;
char *msg = NULL;
/* check module parameter first (override detection) */
if (result >= 0) {
msg = result ? "enable (forced) VM" : "disable (forced) VM";
goto fini;
}
/* detect KVM and Parallels virtual environments */
result = kvm_para_available();
#ifdef X86_FEATURE_HYPERVISOR
result = result || boot_cpu_has(X86_FEATURE_HYPERVISOR);
#endif
if (!result)
goto fini;
/* check for known (emulated) devices */
if (pci->subsystem_vendor == 0x1af4 &&
pci->subsystem_device == 0x1100) {
/* KVM emulated sound, PCI SSID: 1af4:1100 */
msg = "enable KVM";
} else if (pci->subsystem_vendor == 0x1ab8) {
/* Parallels VM emulated sound, PCI SSID: 1ab8:xxxx */
msg = "enable Parallels VM";
} else {
msg = "disable (unknown or VT-d) VM";
result = 0;
}
fini:
if (msg != NULL)
printk(KERN_INFO "intel8x0: %s optimization\n", msg);
return result;
}
static int __devinit snd_intel8x0_create(struct snd_card *card, static int __devinit snd_intel8x0_create(struct snd_card *card,
struct pci_dev *pci, struct pci_dev *pci,
unsigned long device_type, unsigned long device_type,
...@@ -3004,9 +3043,7 @@ static int __devinit snd_intel8x0_create(struct snd_card *card, ...@@ -3004,9 +3043,7 @@ static int __devinit snd_intel8x0_create(struct snd_card *card,
if (xbox) if (xbox)
chip->xbox = 1; chip->xbox = 1;
chip->inside_vm = inside_vm; chip->inside_vm = snd_intel8x0_inside_vm(pci);
if (inside_vm)
printk(KERN_INFO "intel8x0: enable KVM optimization\n");
if (pci->vendor == PCI_VENDOR_ID_INTEL && if (pci->vendor == PCI_VENDOR_ID_INTEL &&
pci->device == PCI_DEVICE_ID_INTEL_440MX) pci->device == PCI_DEVICE_ID_INTEL_440MX)
...@@ -3250,14 +3287,6 @@ static int __devinit snd_intel8x0_probe(struct pci_dev *pci, ...@@ -3250,14 +3287,6 @@ static int __devinit snd_intel8x0_probe(struct pci_dev *pci,
buggy_irq = 0; buggy_irq = 0;
} }
if (inside_vm < 0) {
/* detect KVM and Parallels virtual environments */
inside_vm = kvm_para_available();
#if defined(__i386__) || defined(__x86_64__)
inside_vm = inside_vm || boot_cpu_has(X86_FEATURE_HYPERVISOR);
#endif
}
if ((err = snd_intel8x0_create(card, pci, pci_id->driver_data, if ((err = snd_intel8x0_create(card, pci, pci_id->driver_data,
&chip)) < 0) { &chip)) < 0) {
snd_card_free(card); snd_card_free(card);
......
...@@ -799,6 +799,7 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval, ...@@ -799,6 +799,7 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval,
case USB_ID(0x046d, 0x0808): case USB_ID(0x046d, 0x0808):
case USB_ID(0x046d, 0x0809): case USB_ID(0x046d, 0x0809):
case USB_ID(0x046d, 0x081d): /* HD Webcam c510 */
case USB_ID(0x046d, 0x0991): case USB_ID(0x046d, 0x0991):
/* Most audio usb devices lie about volume resolution. /* Most audio usb devices lie about volume resolution.
* Most Logitech webcams have res = 384. * Most Logitech webcams have res = 384.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment