Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
  ALSA: usb-audio: Use kmemdup rather than duplicating its implementation
  ALSA: hda - Re-enable the check NO_PRESENCE misc bit
  ALSA: vmaster - Free slave-links when freeing the master element
  ALSA: hda - Don't add elements of other codecs to vmaster slave
  ALSA: intel8x0: improve virtual environment detection
  ALSA: intel8x0: move virtual environment detection code into one place
  ALSA: snd_usb_audio: add Logitech HD Webcam c510 to quirk-384
  ALSA: hda - fix internal mic on Dell Vostro 3500 laptop
  ALSA: HDA: Remove quirk for Toshiba T110
  ALSA: usb-audio - Fix the missing volume quirks at delayed init
  ALSA: hda - Mute unused capture sources for Realtek codecs
  ALSA: intel8x0: Improve comments for VM optimization
  ASoC: Ensure we get an impedence reported for WM8958 jack detect
  ASoC: Don't use wm8994->control_data when requesting IRQs
  ASoC: Don't use wm8994->control_data in wm8994_readable_register()
  ASoC: Update git repository URL
This commit is contained in:
Linus Torvalds 2011-11-11 23:45:42 -02:00
commit fe10e6f4b2
14 changed files with 240 additions and 118 deletions

View File

@ -349,6 +349,7 @@ STAC92HD83*
ref Reference board ref Reference board
mic-ref Reference board with power management for ports mic-ref Reference board with power management for ports
dell-s14 Dell laptop dell-s14 Dell laptop
dell-vostro-3500 Dell Vostro 3500 laptop
hp HP laptops with (inverted) mute-LED hp HP laptops with (inverted) mute-LED
hp-dv7-4000 HP dv-7 4000 hp-dv7-4000 HP dv-7 4000
auto BIOS setup (default) auto BIOS setup (default)

View File

@ -6129,7 +6129,7 @@ F: sound/
SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT (ASoC) SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT (ASoC)
M: Liam Girdwood <lrg@ti.com> M: Liam Girdwood <lrg@ti.com>
M: Mark Brown <broonie@opensource.wolfsonmicro.com> M: Mark Brown <broonie@opensource.wolfsonmicro.com>
T: git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound-2.6.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
L: alsa-devel@alsa-project.org (moderated for non-subscribers) L: alsa-devel@alsa-project.org (moderated for non-subscribers)
W: http://alsa-project.org/main/index.php/ASoC W: http://alsa-project.org/main/index.php/ASoC
S: Supported S: Supported

View File

@ -1962,6 +1962,21 @@
#define WM8958_MICB2_DISCH_SHIFT 0 /* MICB2_DISCH */ #define WM8958_MICB2_DISCH_SHIFT 0 /* MICB2_DISCH */
#define WM8958_MICB2_DISCH_WIDTH 1 /* MICB2_DISCH */ #define WM8958_MICB2_DISCH_WIDTH 1 /* MICB2_DISCH */
/*
* R210 (0xD2) - Mic Detect 3
*/
#define WM8958_MICD_LVL_MASK 0x07FC /* MICD_LVL - [10:2] */
#define WM8958_MICD_LVL_SHIFT 2 /* MICD_LVL - [10:2] */
#define WM8958_MICD_LVL_WIDTH 9 /* MICD_LVL - [10:2] */
#define WM8958_MICD_VALID 0x0002 /* MICD_VALID */
#define WM8958_MICD_VALID_MASK 0x0002 /* MICD_VALID */
#define WM8958_MICD_VALID_SHIFT 1 /* MICD_VALID */
#define WM8958_MICD_VALID_WIDTH 1 /* MICD_VALID */
#define WM8958_MICD_STS 0x0001 /* MICD_STS */
#define WM8958_MICD_STS_MASK 0x0001 /* MICD_STS */
#define WM8958_MICD_STS_SHIFT 0 /* MICD_STS */
#define WM8958_MICD_STS_WIDTH 1 /* MICD_STS */
/* /*
* R76 (0x4C) - Charge Pump (1) * R76 (0x4C) - Charge Pump (1)
*/ */

View File

@ -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,
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,
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);
} }

View File

@ -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,
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,
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,
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,
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;

View File

@ -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 */

View File

@ -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 */

View File

@ -3062,7 +3062,6 @@ static const struct snd_pci_quirk cxt5066_cfg_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x1993, "Asus U50F", CXT5066_ASUS), SND_PCI_QUIRK(0x1043, 0x1993, "Asus U50F", CXT5066_ASUS),
SND_PCI_QUIRK(0x1179, 0xff1e, "Toshiba Satellite C650D", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x1179, 0xff1e, "Toshiba Satellite C650D", CXT5066_IDEAPAD),
SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba Satellite P500-PSPGSC-01800T", CXT5066_OLPC_XO_1_5), SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba Satellite P500-PSPGSC-01800T", CXT5066_OLPC_XO_1_5),
SND_PCI_QUIRK(0x1179, 0xffe0, "Toshiba Satellite Pro T130-15F", CXT5066_OLPC_XO_1_5),
SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board", SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board",
CXT5066_LAPTOP), CXT5066_LAPTOP),
SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5), SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5),

View File

@ -284,7 +284,7 @@ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx,
struct alc_spec *spec = codec->spec; struct alc_spec *spec = codec->spec;
const struct hda_input_mux *imux; const struct hda_input_mux *imux;
unsigned int mux_idx; unsigned int mux_idx;
int i, type; int i, type, num_conns;
hda_nid_t nid; hda_nid_t nid;
mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx; mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;
@ -307,16 +307,17 @@ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx,
spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx]; spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx];
/* no selection? */ /* no selection? */
if (snd_hda_get_conn_list(codec, nid, NULL) <= 1) num_conns = snd_hda_get_conn_list(codec, nid, NULL);
if (num_conns <= 1)
return 1; return 1;
type = get_wcaps_type(get_wcaps(codec, nid)); type = get_wcaps_type(get_wcaps(codec, nid));
if (type == AC_WID_AUD_MIX) { if (type == AC_WID_AUD_MIX) {
/* Matrix-mixer style (e.g. ALC882) */ /* Matrix-mixer style (e.g. ALC882) */
for (i = 0; i < imux->num_items; i++) { int active = imux->items[idx].index;
unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE; for (i = 0; i < num_conns; i++) {
snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, unsigned int v = (i == active) ? 0 : HDA_AMP_MUTE;
imux->items[i].index, snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, i,
HDA_AMP_MUTE, v); HDA_AMP_MUTE, v);
} }
} else { } else {

View File

@ -95,6 +95,7 @@ enum {
STAC_92HD83XXX_REF, STAC_92HD83XXX_REF,
STAC_92HD83XXX_PWR_REF, STAC_92HD83XXX_PWR_REF,
STAC_DELL_S14, STAC_DELL_S14,
STAC_DELL_VOSTRO_3500,
STAC_92HD83XXX_HP, STAC_92HD83XXX_HP,
STAC_92HD83XXX_HP_cNB11_INTQUAD, STAC_92HD83XXX_HP_cNB11_INTQUAD,
STAC_HP_DV7_4000, STAC_HP_DV7_4000,
@ -1659,6 +1660,12 @@ static const unsigned int dell_s14_pin_configs[10] = {
0x40f000f0, 0x40f000f0, 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] = { static const unsigned int hp_dv7_4000_pin_configs[10] = {
0x03a12050, 0x0321201f, 0x40f000f0, 0x90170110, 0x03a12050, 0x0321201f, 0x40f000f0, 0x90170110,
0x40f000f0, 0x40f000f0, 0x90170110, 0xd5a30140, 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_REF] = ref92hd83xxx_pin_configs,
[STAC_92HD83XXX_PWR_REF] = ref92hd83xxx_pin_configs, [STAC_92HD83XXX_PWR_REF] = ref92hd83xxx_pin_configs,
[STAC_DELL_S14] = dell_s14_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_92HD83XXX_HP_cNB11_INTQUAD] = hp_cNB11_intquad_pin_configs,
[STAC_HP_DV7_4000] = hp_dv7_4000_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_REF] = "ref",
[STAC_92HD83XXX_PWR_REF] = "mic-ref", [STAC_92HD83XXX_PWR_REF] = "mic-ref",
[STAC_DELL_S14] = "dell-s14", [STAC_DELL_S14] = "dell-s14",
[STAC_DELL_VOSTRO_3500] = "dell-vostro-3500",
[STAC_92HD83XXX_HP] = "hp", [STAC_92HD83XXX_HP] = "hp",
[STAC_92HD83XXX_HP_cNB11_INTQUAD] = "hp_cNB11_intquad", [STAC_92HD83XXX_HP_cNB11_INTQUAD] = "hp_cNB11_intquad",
[STAC_HP_DV7_4000] = "hp-dv7-4000", [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), "DFI LanParty", STAC_92HD83XXX_REF),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ba, SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ba,
"unknown Dell", STAC_DELL_S14), "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, SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xff00, 0x3600,
"HP", STAC_92HD83XXX_HP), "HP", STAC_92HD83XXX_HP),
SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1656, SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1656,

View File

@ -1077,6 +1077,13 @@ static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(struct snd_pcm_substream *subs
} }
if (civ != igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV)) if (civ != igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV))
continue; continue;
/* IO read operation is very expensive inside virtual machine
* as it is emulated. The probability that subsequent PICB read
* will return different result is high enough to loop till
* timeout here.
* Same CIV is strict enough condition to be sure that PICB
* is valid inside VM on emulated card. */
if (chip->inside_vm) if (chip->inside_vm)
break; break;
if (ptr1 == igetword(chip, ichdev->reg_offset + ichdev->roff_picb)) if (ptr1 == igetword(chip, ichdev->reg_offset + ichdev->roff_picb))
@ -2930,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,
@ -2997,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)
@ -3243,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);

View File

@ -56,7 +56,7 @@ static int wm8994_retune_mobile_base[] = {
static int wm8994_readable(struct snd_soc_codec *codec, unsigned int reg) static int wm8994_readable(struct snd_soc_codec *codec, unsigned int reg)
{ {
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
struct wm8994 *control = wm8994->control_data; struct wm8994 *control = codec->control_data;
switch (reg) { switch (reg) {
case WM8994_GPIO_1: case WM8994_GPIO_1:
@ -3030,19 +3030,34 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data)
{ {
struct wm8994_priv *wm8994 = data; struct wm8994_priv *wm8994 = data;
struct snd_soc_codec *codec = wm8994->codec; struct snd_soc_codec *codec = wm8994->codec;
int reg; int reg, count;
reg = snd_soc_read(codec, WM8958_MIC_DETECT_3); /* We may occasionally read a detection without an impedence
if (reg < 0) { * range being provided - if that happens loop again.
dev_err(codec->dev, "Failed to read mic detect status: %d\n", */
reg); count = 10;
return IRQ_NONE; do {
} reg = snd_soc_read(codec, WM8958_MIC_DETECT_3);
if (reg < 0) {
dev_err(codec->dev,
"Failed to read mic detect status: %d\n",
reg);
return IRQ_NONE;
}
if (!(reg & WM8958_MICD_VALID)) { if (!(reg & WM8958_MICD_VALID)) {
dev_dbg(codec->dev, "Mic detect data not valid\n"); dev_dbg(codec->dev, "Mic detect data not valid\n");
goto out; goto out;
} }
if (!(reg & WM8958_MICD_STS) || (reg & WM8958_MICD_LVL_MASK))
break;
msleep(1);
} while (count--);
if (count == 0)
dev_warn(codec->dev, "No impedence range reported for jack\n");
#ifndef CONFIG_SND_SOC_WM8994_MODULE #ifndef CONFIG_SND_SOC_WM8994_MODULE
trace_snd_soc_jack_irq(dev_name(codec->dev)); trace_snd_soc_jack_irq(dev_name(codec->dev));
@ -3180,9 +3195,9 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
wm8994_request_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR, wm8994_request_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR,
wm8994_fifo_error, "FIFO error", codec); wm8994_fifo_error, "FIFO error", codec);
wm8994_request_irq(wm8994->control_data, WM8994_IRQ_TEMP_WARN, wm8994_request_irq(codec->control_data, WM8994_IRQ_TEMP_WARN,
wm8994_temp_warn, "Thermal warning", codec); wm8994_temp_warn, "Thermal warning", codec);
wm8994_request_irq(wm8994->control_data, WM8994_IRQ_TEMP_SHUT, wm8994_request_irq(codec->control_data, WM8994_IRQ_TEMP_SHUT,
wm8994_temp_shut, "Thermal shutdown", codec); wm8994_temp_shut, "Thermal shutdown", codec);
ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_DCS_DONE, ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_DCS_DONE,

View File

@ -765,10 +765,61 @@ static void usb_mixer_elem_free(struct snd_kcontrol *kctl)
* interface to ALSA control for feature/mixer units * interface to ALSA control for feature/mixer units
*/ */
/* volume control quirks */
static void volume_control_quirks(struct usb_mixer_elem_info *cval,
struct snd_kcontrol *kctl)
{
switch (cval->mixer->chip->usb_id) {
case USB_ID(0x0471, 0x0101):
case USB_ID(0x0471, 0x0104):
case USB_ID(0x0471, 0x0105):
case USB_ID(0x0672, 0x1041):
/* quirk for UDA1321/N101.
* note that detection between firmware 2.1.1.7 (N101)
* and later 2.1.1.21 is not very clear from datasheets.
* I hope that the min value is -15360 for newer firmware --jk
*/
if (!strcmp(kctl->id.name, "PCM Playback Volume") &&
cval->min == -15616) {
snd_printk(KERN_INFO
"set volume quirk for UDA1321/N101 chip\n");
cval->max = -256;
}
break;
case USB_ID(0x046d, 0x09a4):
if (!strcmp(kctl->id.name, "Mic Capture Volume")) {
snd_printk(KERN_INFO
"set volume quirk for QuickCam E3500\n");
cval->min = 6080;
cval->max = 8768;
cval->res = 192;
}
break;
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.
* Proboly there is some logitech magic behind this number --fishor
*/
if (!strcmp(kctl->id.name, "Mic Capture Volume")) {
snd_printk(KERN_INFO
"set resolution quirk: cval->res = 384\n");
cval->res = 384;
}
break;
}
}
/* /*
* retrieve the minimum and maximum values for the specified control * retrieve the minimum and maximum values for the specified control
*/ */
static int get_min_max(struct usb_mixer_elem_info *cval, int default_min) static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval,
int default_min, struct snd_kcontrol *kctl)
{ {
/* for failsafe */ /* for failsafe */
cval->min = default_min; cval->min = default_min;
@ -844,6 +895,9 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
cval->initialized = 1; cval->initialized = 1;
} }
if (kctl)
volume_control_quirks(cval, kctl);
/* USB descriptions contain the dB scale in 1/256 dB unit /* USB descriptions contain the dB scale in 1/256 dB unit
* while ALSA TLV contains in 1/100 dB unit * while ALSA TLV contains in 1/100 dB unit
*/ */
@ -864,6 +918,7 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
return 0; return 0;
} }
#define get_min_max(cval, def) get_min_max_with_quirks(cval, def, NULL)
/* get a feature/mixer unit info */ /* get a feature/mixer unit info */
static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
@ -882,7 +937,7 @@ static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol, struct snd_ctl_
uinfo->value.integer.max = 1; uinfo->value.integer.max = 1;
} else { } else {
if (!cval->initialized) { if (!cval->initialized) {
get_min_max(cval, 0); get_min_max_with_quirks(cval, 0, kcontrol);
if (cval->initialized && cval->dBmin >= cval->dBmax) { if (cval->initialized && cval->dBmin >= cval->dBmax) {
kcontrol->vd[0].access &= kcontrol->vd[0].access &=
~(SNDRV_CTL_ELEM_ACCESS_TLV_READ | ~(SNDRV_CTL_ELEM_ACCESS_TLV_READ |
@ -1045,9 +1100,6 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
cval->ch_readonly = readonly_mask; cval->ch_readonly = readonly_mask;
} }
/* get min/max values */
get_min_max(cval, 0);
/* if all channels in the mask are marked read-only, make the control /* if all channels in the mask are marked read-only, make the control
* read-only. set_cur_mix_value() will check the mask again and won't * read-only. set_cur_mix_value() will check the mask again and won't
* issue write commands to read-only channels. */ * issue write commands to read-only channels. */
@ -1069,6 +1121,9 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
len = snd_usb_copy_string_desc(state, nameid, len = snd_usb_copy_string_desc(state, nameid,
kctl->id.name, sizeof(kctl->id.name)); kctl->id.name, sizeof(kctl->id.name));
/* get min/max values */
get_min_max_with_quirks(cval, 0, kctl);
switch (control) { switch (control) {
case UAC_FU_MUTE: case UAC_FU_MUTE:
case UAC_FU_VOLUME: case UAC_FU_VOLUME:
@ -1118,51 +1173,6 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
break; break;
} }
/* volume control quirks */
switch (state->chip->usb_id) {
case USB_ID(0x0471, 0x0101):
case USB_ID(0x0471, 0x0104):
case USB_ID(0x0471, 0x0105):
case USB_ID(0x0672, 0x1041):
/* quirk for UDA1321/N101.
* note that detection between firmware 2.1.1.7 (N101)
* and later 2.1.1.21 is not very clear from datasheets.
* I hope that the min value is -15360 for newer firmware --jk
*/
if (!strcmp(kctl->id.name, "PCM Playback Volume") &&
cval->min == -15616) {
snd_printk(KERN_INFO
"set volume quirk for UDA1321/N101 chip\n");
cval->max = -256;
}
break;
case USB_ID(0x046d, 0x09a4):
if (!strcmp(kctl->id.name, "Mic Capture Volume")) {
snd_printk(KERN_INFO
"set volume quirk for QuickCam E3500\n");
cval->min = 6080;
cval->max = 8768;
cval->res = 192;
}
break;
case USB_ID(0x046d, 0x0808):
case USB_ID(0x046d, 0x0809):
case USB_ID(0x046d, 0x0991):
/* Most audio usb devices lie about volume resolution.
* Most Logitech webcams have res = 384.
* Proboly there is some logitech magic behind this number --fishor
*/
if (!strcmp(kctl->id.name, "Mic Capture Volume")) {
snd_printk(KERN_INFO
"set resolution quirk: cval->res = 384\n");
cval->res = 384;
}
break;
}
range = (cval->max - cval->min) / cval->res; range = (cval->max - cval->min) / cval->res;
/* Are there devices with volume range more than 255? I use a bit more /* Are there devices with volume range more than 255? I use a bit more
* to be sure. 384 is a resolution magic number found on Logitech * to be sure. 384 is a resolution magic number found on Logitech

View File

@ -137,12 +137,12 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
return -ENOMEM; return -ENOMEM;
} }
if (fp->nr_rates > 0) { 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) { if (!rate_table) {
kfree(fp); kfree(fp);
return -ENOMEM; return -ENOMEM;
} }
memcpy(rate_table, fp->rate_table, sizeof(int) * fp->nr_rates);
fp->rate_table = rate_table; fp->rate_table = rate_table;
} }
@ -224,10 +224,9 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip,
if (altsd->bNumEndpoints != 1) if (altsd->bNumEndpoints != 1)
return -ENXIO; return -ENXIO;
fp = kmalloc(sizeof(*fp), GFP_KERNEL); fp = kmemdup(&ua_format, sizeof(*fp), GFP_KERNEL);
if (!fp) if (!fp)
return -ENOMEM; return -ENOMEM;
memcpy(fp, &ua_format, sizeof(*fp));
fp->iface = altsd->bInterfaceNumber; fp->iface = altsd->bInterfaceNumber;
fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;