Loading sound/core/vmaster.c +14 −4 Original line number Diff line number Diff line Loading @@ -52,6 +52,7 @@ struct link_slave { struct link_ctl_info info; int vals[2]; /* current values */ unsigned int flags; struct snd_kcontrol *kctl; /* original kcontrol pointer */ struct snd_kcontrol slave; /* the copy of original control entry */ }; Loading Loading @@ -252,6 +253,7 @@ int _snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave, slave->count * sizeof(*slave->vd), GFP_KERNEL); if (!srec) return -ENOMEM; srec->kctl = slave; srec->slave = *slave; memcpy(srec->slave.vd, slave->vd, slave->count * sizeof(*slave->vd)); srec->master = master_link; Loading Loading @@ -333,10 +335,18 @@ static int master_put(struct snd_kcontrol *kcontrol, static void master_free(struct snd_kcontrol *kcontrol) { struct link_master *master = snd_kcontrol_chip(kcontrol); struct link_slave *slave; list_for_each_entry(slave, &master->slaves, list) slave->master = NULL; struct link_slave *slave, *n; /* free all slave links and retore the original slave kctls */ 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); } Loading sound/pci/hda/hda_codec.c +43 −21 Original line number Diff line number Diff line Loading @@ -2331,6 +2331,39 @@ int snd_hda_codec_reset(struct hda_codec *codec) 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 * @codec: HD-audio codec Loading @@ -2351,12 +2384,10 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name, unsigned int *tlv, const char * const *slaves) { struct snd_kcontrol *kctl; const char * const *s; int err; for (s = slaves; *s && !snd_hda_find_mixer_ctl(codec, *s); s++) ; if (!*s) { err = map_slaves(codec, slaves, check_slave_present, NULL); if (err != 1) { snd_printdd("No slave found for %s\n", name); return 0; } Loading @@ -2367,23 +2398,10 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name, if (err < 0) return err; for (s = slaves; *s; s++) { struct snd_kcontrol *sctl; int i = 0; for (;;) { 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); err = map_slaves(codec, slaves, (map_slave_func_t)snd_ctl_add_slave, kctl); if (err < 0) return err; i++; } } return 0; } EXPORT_SYMBOL_HDA(snd_hda_add_vmaster); Loading Loading @@ -4752,6 +4770,7 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec, memset(sequences_hp, 0, sizeof(sequences_hp)); assoc_line_out = 0; codec->ignore_misc_bit = true; end_nid = codec->start_nid + codec->num_nodes; for (nid = codec->start_nid; nid < end_nid; nid++) { unsigned int wid_caps = get_wcaps(codec, nid); Loading @@ -4767,6 +4786,9 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec, continue; 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); if (conn == AC_JACK_PORT_NONE) continue; Loading sound/pci/hda/hda_codec.h +1 −0 Original line number Diff line number Diff line Loading @@ -854,6 +854,7 @@ struct hda_codec { unsigned int no_sticky_stream:1; /* no sticky-PCM stream assignment */ unsigned int pins_shutup:1; /* pins are shut up */ 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 unsigned int power_on :1; /* current (global) power-state */ unsigned int power_transition :1; /* power-state in transition */ Loading sound/pci/hda/hda_local.h +9 −7 Original line number Diff line number Diff line Loading @@ -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) { return (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_PRES_DETECT) && /* disable MISC_NO_PRESENCE check because it may break too * many devices */ /*(get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid) & AC_DEFCFG_MISC_NO_PRESENCE)) &&*/ (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP); if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_PRES_DETECT)) return false; if (!codec->ignore_misc_bit && (get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) & AC_DEFCFG_MISC_NO_PRESENCE)) return false; if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP)) return false; return true; } /* flags for hda_nid_item */ Loading sound/pci/intel8x0.c +40 −11 Original line number Diff line number Diff line Loading @@ -2937,6 +2937,45 @@ static unsigned int sis_codec_bits[3] = { 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, struct pci_dev *pci, unsigned long device_type, Loading Loading @@ -3004,9 +3043,7 @@ static int __devinit snd_intel8x0_create(struct snd_card *card, if (xbox) chip->xbox = 1; chip->inside_vm = inside_vm; if (inside_vm) printk(KERN_INFO "intel8x0: enable KVM optimization\n"); chip->inside_vm = snd_intel8x0_inside_vm(pci); if (pci->vendor == PCI_VENDOR_ID_INTEL && pci->device == PCI_DEVICE_ID_INTEL_440MX) Loading Loading @@ -3250,14 +3287,6 @@ static int __devinit snd_intel8x0_probe(struct pci_dev *pci, 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, &chip)) < 0) { snd_card_free(card); Loading Loading
sound/core/vmaster.c +14 −4 Original line number Diff line number Diff line Loading @@ -52,6 +52,7 @@ struct link_slave { struct link_ctl_info info; int vals[2]; /* current values */ unsigned int flags; struct snd_kcontrol *kctl; /* original kcontrol pointer */ struct snd_kcontrol slave; /* the copy of original control entry */ }; Loading Loading @@ -252,6 +253,7 @@ int _snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave, slave->count * sizeof(*slave->vd), GFP_KERNEL); if (!srec) return -ENOMEM; srec->kctl = slave; srec->slave = *slave; memcpy(srec->slave.vd, slave->vd, slave->count * sizeof(*slave->vd)); srec->master = master_link; Loading Loading @@ -333,10 +335,18 @@ static int master_put(struct snd_kcontrol *kcontrol, static void master_free(struct snd_kcontrol *kcontrol) { struct link_master *master = snd_kcontrol_chip(kcontrol); struct link_slave *slave; list_for_each_entry(slave, &master->slaves, list) slave->master = NULL; struct link_slave *slave, *n; /* free all slave links and retore the original slave kctls */ 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); } Loading
sound/pci/hda/hda_codec.c +43 −21 Original line number Diff line number Diff line Loading @@ -2331,6 +2331,39 @@ int snd_hda_codec_reset(struct hda_codec *codec) 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 * @codec: HD-audio codec Loading @@ -2351,12 +2384,10 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name, unsigned int *tlv, const char * const *slaves) { struct snd_kcontrol *kctl; const char * const *s; int err; for (s = slaves; *s && !snd_hda_find_mixer_ctl(codec, *s); s++) ; if (!*s) { err = map_slaves(codec, slaves, check_slave_present, NULL); if (err != 1) { snd_printdd("No slave found for %s\n", name); return 0; } Loading @@ -2367,23 +2398,10 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name, if (err < 0) return err; for (s = slaves; *s; s++) { struct snd_kcontrol *sctl; int i = 0; for (;;) { 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); err = map_slaves(codec, slaves, (map_slave_func_t)snd_ctl_add_slave, kctl); if (err < 0) return err; i++; } } return 0; } EXPORT_SYMBOL_HDA(snd_hda_add_vmaster); Loading Loading @@ -4752,6 +4770,7 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec, memset(sequences_hp, 0, sizeof(sequences_hp)); assoc_line_out = 0; codec->ignore_misc_bit = true; end_nid = codec->start_nid + codec->num_nodes; for (nid = codec->start_nid; nid < end_nid; nid++) { unsigned int wid_caps = get_wcaps(codec, nid); Loading @@ -4767,6 +4786,9 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec, continue; 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); if (conn == AC_JACK_PORT_NONE) continue; Loading
sound/pci/hda/hda_codec.h +1 −0 Original line number Diff line number Diff line Loading @@ -854,6 +854,7 @@ struct hda_codec { unsigned int no_sticky_stream:1; /* no sticky-PCM stream assignment */ unsigned int pins_shutup:1; /* pins are shut up */ 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 unsigned int power_on :1; /* current (global) power-state */ unsigned int power_transition :1; /* power-state in transition */ Loading
sound/pci/hda/hda_local.h +9 −7 Original line number Diff line number Diff line Loading @@ -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) { return (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_PRES_DETECT) && /* disable MISC_NO_PRESENCE check because it may break too * many devices */ /*(get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid) & AC_DEFCFG_MISC_NO_PRESENCE)) &&*/ (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP); if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_PRES_DETECT)) return false; if (!codec->ignore_misc_bit && (get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) & AC_DEFCFG_MISC_NO_PRESENCE)) return false; if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP)) return false; return true; } /* flags for hda_nid_item */ Loading
sound/pci/intel8x0.c +40 −11 Original line number Diff line number Diff line Loading @@ -2937,6 +2937,45 @@ static unsigned int sis_codec_bits[3] = { 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, struct pci_dev *pci, unsigned long device_type, Loading Loading @@ -3004,9 +3043,7 @@ static int __devinit snd_intel8x0_create(struct snd_card *card, if (xbox) chip->xbox = 1; chip->inside_vm = inside_vm; if (inside_vm) printk(KERN_INFO "intel8x0: enable KVM optimization\n"); chip->inside_vm = snd_intel8x0_inside_vm(pci); if (pci->vendor == PCI_VENDOR_ID_INTEL && pci->device == PCI_DEVICE_ID_INTEL_440MX) Loading Loading @@ -3250,14 +3287,6 @@ static int __devinit snd_intel8x0_probe(struct pci_dev *pci, 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, &chip)) < 0) { snd_card_free(card); Loading