From f7f9bdfadfda07afb904a9767468e38c2d1a6033 Mon Sep 17 00:00:00 2001 From: Julian Wollrath Date: Wed, 9 Nov 2011 10:02:40 +0100 Subject: ALSA: hda - fix internal mic on Dell Vostro 3500 laptop Fix the not working internal mic on Dell Vostro 3500 laptop by introducing the new model dell-vostro-3500. Signed-off-by: Julian Wollrath Cc: Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'sound') diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 4e715fefebef..edc2b7bc177c 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -95,6 +95,7 @@ enum { STAC_92HD83XXX_REF, STAC_92HD83XXX_PWR_REF, STAC_DELL_S14, + STAC_DELL_VOSTRO_3500, STAC_92HD83XXX_HP, STAC_92HD83XXX_HP_cNB11_INTQUAD, STAC_HP_DV7_4000, @@ -1659,6 +1660,12 @@ static const unsigned int dell_s14_pin_configs[10] = { 0x40f000f0, 0x40f000f0, }; +static const unsigned int dell_vostro_3500_pin_configs[10] = { + 0x02a11020, 0x0221101f, 0x400000f0, 0x90170110, + 0x400000f1, 0x400000f2, 0x400000f3, 0x90a60160, + 0x400000f4, 0x400000f5, +}; + static const unsigned int hp_dv7_4000_pin_configs[10] = { 0x03a12050, 0x0321201f, 0x40f000f0, 0x90170110, 0x40f000f0, 0x40f000f0, 0x90170110, 0xd5a30140, @@ -1675,6 +1682,7 @@ static const unsigned int *stac92hd83xxx_brd_tbl[STAC_92HD83XXX_MODELS] = { [STAC_92HD83XXX_REF] = ref92hd83xxx_pin_configs, [STAC_92HD83XXX_PWR_REF] = ref92hd83xxx_pin_configs, [STAC_DELL_S14] = dell_s14_pin_configs, + [STAC_DELL_VOSTRO_3500] = dell_vostro_3500_pin_configs, [STAC_92HD83XXX_HP_cNB11_INTQUAD] = hp_cNB11_intquad_pin_configs, [STAC_HP_DV7_4000] = hp_dv7_4000_pin_configs, }; @@ -1684,6 +1692,7 @@ static const char * const stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = { [STAC_92HD83XXX_REF] = "ref", [STAC_92HD83XXX_PWR_REF] = "mic-ref", [STAC_DELL_S14] = "dell-s14", + [STAC_DELL_VOSTRO_3500] = "dell-vostro-3500", [STAC_92HD83XXX_HP] = "hp", [STAC_92HD83XXX_HP_cNB11_INTQUAD] = "hp_cNB11_intquad", [STAC_HP_DV7_4000] = "hp-dv7-4000", @@ -1697,6 +1706,8 @@ static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { "DFI LanParty", STAC_92HD83XXX_REF), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ba, "unknown Dell", STAC_DELL_S14), + SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x1028, + "Dell Vostro 3500", STAC_DELL_VOSTRO_3500), SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xff00, 0x3600, "HP", STAC_92HD83XXX_HP), SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1656, -- cgit v1.2.3 From 55c0008be67a27944b6705251d9a8d4c56c67701 Mon Sep 17 00:00:00 2001 From: Alexey Fisher Date: Wed, 9 Nov 2011 11:39:24 +0100 Subject: ALSA: snd_usb_audio: add Logitech HD Webcam c510 to quirk-384 Logitech HD Webcam c510 provide wrong mixer resolution. Add it to "res = 384" quirk. Signed-off-by: Alexey Fisher Signed-off-by: Takashi Iwai --- sound/usb/mixer.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound') diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index c5444e00f0c6..ab23869c01bb 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -799,6 +799,7 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval, case USB_ID(0x046d, 0x0808): case USB_ID(0x046d, 0x0809): + case USB_ID(0x046d, 0x081d): /* HD Webcam c510 */ case USB_ID(0x046d, 0x0991): /* Most audio usb devices lie about volume resolution. * Most Logitech webcams have res = 384. -- cgit v1.2.3 From 65c397d6b58d5e401bee7c24608d3a33a220a63a Mon Sep 17 00:00:00 2001 From: Konstantin Ozerkov Date: Wed, 9 Nov 2011 19:28:54 +0400 Subject: ALSA: intel8x0: move virtual environment detection code into one place This is refactoring patch: preparation for add improved detection code. Now all detection code placed in one place. Signed-off-by: Konstantin Ozerkov Signed-off-by: Denis V. Lunev Signed-off-by: Takashi Iwai --- sound/pci/intel8x0.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) (limited to 'sound') diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index c3b9bd0e188e..2d4bb4c9a030 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -2937,6 +2937,24 @@ static unsigned int sis_codec_bits[3] = { ICH_PCR, ICH_SCR, ICH_SIS_TCR }; +static int __devinit snd_intel8x0_inside_vm(void) +{ + int result = inside_vm; + + if (result < 0) { + /* detect KVM and Parallels virtual environments */ + result = kvm_para_available(); +#if defined(__i386__) || defined(__x86_64__) + result = result || boot_cpu_has(X86_FEATURE_HYPERVISOR); +#endif + } + + if (result) + printk(KERN_INFO "intel8x0: enable KVM optimization\n"); + + return result; +} + static int __devinit snd_intel8x0_create(struct snd_card *card, struct pci_dev *pci, unsigned long device_type, @@ -3004,9 +3022,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(); if (pci->vendor == PCI_VENDOR_ID_INTEL && pci->device == PCI_DEVICE_ID_INTEL_440MX) @@ -3250,14 +3266,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); -- cgit v1.2.3 From 7fb4f392bd27e5b0e2444430d241370837bcc8fa Mon Sep 17 00:00:00 2001 From: Konstantin Ozerkov Date: Wed, 9 Nov 2011 19:28:55 +0400 Subject: ALSA: intel8x0: improve virtual environment detection Detection code improved by PCI SSID usage. VM optimization now enabled only for known devcices (skip host devices forwarded to VM by VT-d or same kind of technology). For debug/troubleshooting purposes optimization can be forced (on/off) by module parameter: "inside_vm" (boolean). Known devices (PCI SSID): 1af4:1100: Reserved for KVM devices. Note this is not yet implemented for KVM's ICH/AC'97 emulation. 1ab8:xxxx: Parallels ICH/AC'97 emulated sound. [ fixed a minor coding-style issue by tiwai] Signed-off-by: Konstantin Ozerkov Signed-off-by: Denis V. Lunev Signed-off-by: Takashi Iwai --- sound/pci/intel8x0.c | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) (limited to 'sound') diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 2d4bb4c9a030..11718b49b2e2 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -2937,20 +2937,41 @@ static unsigned int sis_codec_bits[3] = { ICH_PCR, ICH_SCR, ICH_SIS_TCR }; -static int __devinit snd_intel8x0_inside_vm(void) +static int __devinit snd_intel8x0_inside_vm(struct pci_dev *pci) { - int result = inside_vm; + int result = inside_vm; + char *msg = NULL; - if (result < 0) { - /* detect KVM and Parallels virtual environments */ - result = kvm_para_available(); -#if defined(__i386__) || defined(__x86_64__) - result = result || boot_cpu_has(X86_FEATURE_HYPERVISOR); + /* 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; } - if (result) - printk(KERN_INFO "intel8x0: enable KVM optimization\n"); +fini: + if (msg != NULL) + printk(KERN_INFO "intel8x0: %s optimization\n", msg); return result; } @@ -3022,7 +3043,7 @@ static int __devinit snd_intel8x0_create(struct snd_card *card, if (xbox) chip->xbox = 1; - chip->inside_vm = snd_intel8x0_inside_vm(); + chip->inside_vm = snd_intel8x0_inside_vm(pci); if (pci->vendor == PCI_VENDOR_ID_INTEL && pci->device == PCI_DEVICE_ID_INTEL_440MX) -- cgit v1.2.3 From aeb4b88ec0a948efce8e3a23a8f964d3560a7308 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 10 Nov 2011 12:28:38 +0100 Subject: ALSA: hda - Don't add elements of other codecs to vmaster slave When a virtual mater control is created, the driver looks for slave elements from the assigned card instance. But this may include the elements of other codecs when multiple codecs are on the same HD-audio bus. This works at the first time, but it'll give Oops when it's once freed and re-created via reconfig sysfs. This patch changes the element-look-up strategy to limit only to the mixer elements of the same codec. Reported-by: David Henningsson Cc: Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 60 ++++++++++++++++++++++++++++++----------------- 1 file changed, 39 insertions(+), 21 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 916a1863af73..e9136711b2d5 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -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 @@ -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; } @@ -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); - if (err < 0) - return err; - i++; - } - } + err = map_slaves(codec, slaves, (map_slave_func_t)snd_ctl_add_slave, + kctl); + if (err < 0) + return err; return 0; } EXPORT_SYMBOL_HDA(snd_hda_add_vmaster); -- cgit v1.2.3 From 9e226b4b7e77215ca70461edc33800f6c1ba63d3 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 10 Nov 2011 12:34:24 +0100 Subject: ALSA: vmaster - Free slave-links when freeing the master element When freeing the vmaster master element, we should release slave-links properly, not only assumig that slaves will be freed soon later. Signed-off-by: Takashi Iwai --- sound/core/vmaster.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/core/vmaster.c b/sound/core/vmaster.c index 5dbab38d04af..130cfe677d60 100644 --- a/sound/core/vmaster.c +++ b/sound/core/vmaster.c @@ -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 */ }; @@ -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; @@ -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); } -- cgit v1.2.3 From 2f451d2a2a44b66586b803763068195088f9ccd4 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 10 Nov 2011 12:36:46 +0100 Subject: ALSA: hda - Re-enable the check NO_PRESENCE misc bit We disabled the check of NO_PRESENCE bit of the default pin-config in commit f4419172 temporarily. One problem was that the first implementation was wrong -- the bit after the shift must be checked. However, this would still give many regressions on machines with broken BIOS. They set this bit wrongly even on active pins. A workaround is to check whether all pins contain this bit. As far as I've checked, broken BIOSen set this bit on all pins, no matter whether active or not. In such a case, the driver should ignore this bit check. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 4 ++++ sound/pci/hda/hda_codec.h | 1 + sound/pci/hda/hda_local.h | 16 +++++++++------- 3 files changed, 14 insertions(+), 7 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index e9136711b2d5..e44b107fdc75 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -4770,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); @@ -4785,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; diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 755f2b0f9d8e..564471169cae 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h @@ -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 */ diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index dcbea0da0fa2..6579e0f2bb57 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h @@ -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 */ -- cgit v1.2.3 From 43df2a57b773596cd0bdd2316889ff9653121015 Mon Sep 17 00:00:00 2001 From: Thomas Meyer Date: Thu, 10 Nov 2011 19:38:43 +0100 Subject: ALSA: usb-audio: Use kmemdup rather than duplicating its implementation Use kmemdup rather than duplicating its implementation The semantic patch that makes this change is available in scripts/coccinelle/api/memdup.cocci. Signed-off-by: Thomas Meyer Signed-off-by: Takashi Iwai --- sound/usb/quirks.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 2e5bc7344026..a3ddac0deffd 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -137,12 +137,12 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip, return -ENOMEM; } if (fp->nr_rates > 0) { - rate_table = kmalloc(sizeof(int) * fp->nr_rates, GFP_KERNEL); + rate_table = kmemdup(fp->rate_table, + sizeof(int) * fp->nr_rates, GFP_KERNEL); if (!rate_table) { kfree(fp); return -ENOMEM; } - memcpy(rate_table, fp->rate_table, sizeof(int) * fp->nr_rates); fp->rate_table = rate_table; } @@ -224,10 +224,9 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip, if (altsd->bNumEndpoints != 1) return -ENXIO; - fp = kmalloc(sizeof(*fp), GFP_KERNEL); + fp = kmemdup(&ua_format, sizeof(*fp), GFP_KERNEL); if (!fp) return -ENOMEM; - memcpy(fp, &ua_format, sizeof(*fp)); fp->iface = altsd->bInterfaceNumber; fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; -- cgit v1.2.3