From 86f14df8ed1ecec5cefe7d002b4d297e298238c2 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 2 Nov 2011 21:36:32 +0000 Subject: ASoC: Update git repository URL Remove the -2.6 from the name. Signed-off-by: Mark Brown --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index bbf42cd74e2a..63b58dd1561e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6001,7 +6001,7 @@ F: sound/ SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT (ASoC) M: Liam Girdwood M: Mark Brown -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) W: http://alsa-project.org/main/index.php/ASoC S: Supported -- cgit From 8eeea521d9d0fa6afd62df8c6e6566ee946117fa Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 4 Nov 2011 15:52:31 +0000 Subject: ASoC: Don't use wm8994->control_data in wm8994_readable_register() The field is no longer initialised so this will crash if running on wm8958. Reported-by: Thomas Abraham Signed-off-by: Mark Brown Cc: stable@kernel.org --- sound/soc/codecs/wm8994.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 6b73efd26991..3d2c3d4711d0 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -56,7 +56,7 @@ static int wm8994_retune_mobile_base[] = { static int wm8994_readable(struct snd_soc_codec *codec, unsigned int reg) { struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - struct wm8994 *control = wm8994->control_data; + struct wm8994 *control = codec->control_data; switch (reg) { case WM8994_GPIO_1: -- cgit From 5a3ad6bd6ae0687cb0ecb424d74221920fbc7f38 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 4 Nov 2011 15:53:48 +0000 Subject: ASoC: Don't use wm8994->control_data when requesting IRQs The field is no longer initialised so this will crash if running on wm8958. Reported-by: Thomas Abraham Signed-off-by: Mark Brown --- sound/soc/codecs/wm8994.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 3d2c3d4711d0..9cb16cc853b3 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -3180,9 +3180,9 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) wm8994_request_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR, 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_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); ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_DCS_DONE, -- cgit From 19940b3d55c87d8089a8cb0fa8e5a9918a3846bd Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 19 Aug 2011 18:05:05 +0900 Subject: ASoC: Ensure we get an impedence reported for WM8958 jack detect Occasionally we may see an accessory reported before we have a stable impedance for the accessory. If this happens then reread the status in order to ensure that the handler can take the appropriate action for the status change. Signed-off-by: Mark Brown --- include/linux/mfd/wm8994/registers.h | 15 +++++++++++++++ sound/soc/codecs/wm8994.c | 37 +++++++++++++++++++++++++----------- 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/include/linux/mfd/wm8994/registers.h b/include/linux/mfd/wm8994/registers.h index fae295048a8b..83a9caec0e43 100644 --- a/include/linux/mfd/wm8994/registers.h +++ b/include/linux/mfd/wm8994/registers.h @@ -1962,6 +1962,21 @@ #define WM8958_MICB2_DISCH_SHIFT 0 /* 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) */ diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 9cb16cc853b3..9c982e47eb99 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -3030,19 +3030,34 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data) { struct wm8994_priv *wm8994 = data; struct snd_soc_codec *codec = wm8994->codec; - int reg; + int reg, count; - 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; - } + /* We may occasionally read a detection without an impedence + * range being provided - if that happens loop again. + */ + count = 10; + 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)) { - dev_dbg(codec->dev, "Mic detect data not valid\n"); - goto out; - } + if (!(reg & WM8958_MICD_VALID)) { + dev_dbg(codec->dev, "Mic detect data not valid\n"); + 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 trace_snd_soc_jack_irq(dev_name(codec->dev)); -- cgit From 5a9a51799b23142d2fc3ef94894d3b5ac00d05a5 Mon Sep 17 00:00:00 2001 From: "Denis V. Lunev" Date: Mon, 7 Nov 2011 20:33:25 +0400 Subject: ALSA: intel8x0: Improve comments for VM optimization The recently merged 228cf79376f1 looks a bit hackish while it is not. The change was quite simple. In a virtualized environment the patch unhacks old kludge introduced for old broken AC97 hardware. This patch adds proper comment to "unkludge" code. Signed-off-by: Denis V. Lunev Signed-off-by: Konstantin Ozerkov Signed-off-by: Takashi Iwai --- sound/pci/intel8x0.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 29e312597f20..c3b9bd0e188e 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -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)) 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) break; if (ptr1 == igetword(chip, ichdev->reg_offset + ichdev->roff_picb)) -- cgit From dccc1810f41b42773a2e359907f05a7fd10910bd Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 8 Nov 2011 07:52:19 +0100 Subject: ALSA: hda - Mute unused capture sources for Realtek codecs When a Realtek codec has a matrix-style capture-source selection, we need to scan all connections instead of only imux items. Otherwise some input might be kept unmuted. Although the corresponding input must be dead so there should be no input from it, it's still safer to mute the route completely. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index a24e068a021b..308bb575bc06 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -284,7 +284,7 @@ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx, struct alc_spec *spec = codec->spec; const struct hda_input_mux *imux; unsigned int mux_idx; - int i, type; + int i, type, num_conns; hda_nid_t nid; 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]; /* 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; type = get_wcaps_type(get_wcaps(codec, nid)); if (type == AC_WID_AUD_MIX) { /* Matrix-mixer style (e.g. ALC882) */ - for (i = 0; i < imux->num_items; i++) { - unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE; - snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, - imux->items[i].index, + int active = imux->items[idx].index; + for (i = 0; i < num_conns; i++) { + unsigned int v = (i == active) ? 0 : HDA_AMP_MUTE; + snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, i, HDA_AMP_MUTE, v); } } else { -- cgit From f1e10354fc2a12773e5e8efcf841380aa57d4aa5 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 5 Nov 2011 14:47:19 +0800 Subject: ASoC: wm9081: Fix reading wrong register for setting VMID 2*240k VMID Divider Enable and Select is controlled by BIT[2:1] of WM9081_VMID_CONTROL register (04h). Current code reads wrong register (WM9081_BIAS_CONTROL_1) for setting VMID 2*240k. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- sound/soc/codecs/wm9081.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index 3cd35a02c28c..fe6561885f39 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c @@ -818,7 +818,7 @@ static int wm9081_set_bias_level(struct snd_soc_codec *codec, } /* VMID 2*240k */ - reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1); + reg = snd_soc_read(codec, WM9081_VMID_CONTROL); reg &= ~WM9081_VMID_SEL_MASK; reg |= 0x04; snd_soc_write(codec, WM9081_VMID_CONTROL, reg); -- cgit From adf463626ad8e0a2cdbe17d8bb64c1d9d0ac160d Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 5 Nov 2011 14:49:21 +0800 Subject: ASoC: wm9081: Don't write WM9081_BIAS_ENA bit to WM9081_VMID_CONTROL register WM9081_BIAS_ENA is the bit[1] of WM9081_BIAS_CONTROL_1 register (05h). Current code incorrectly write it to WM9081_VMID_CONTROL(04h) register. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- sound/soc/codecs/wm9081.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index fe6561885f39..4a398c3bfe84 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c @@ -807,7 +807,6 @@ static int wm9081_set_bias_level(struct snd_soc_codec *codec, mdelay(100); /* Normal bias enable & soft start off */ - reg |= WM9081_BIAS_ENA; reg &= ~WM9081_VMID_RAMP; snd_soc_write(codec, WM9081_VMID_CONTROL, reg); @@ -830,14 +829,15 @@ static int wm9081_set_bias_level(struct snd_soc_codec *codec, break; case SND_SOC_BIAS_OFF: - /* Startup bias source */ + /* Startup bias source and disable bias */ reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1); reg |= WM9081_BIAS_SRC; + reg &= ~WM9081_BIAS_ENA; snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg); - /* Disable VMID and biases with soft ramping */ + /* Disable VMID with soft ramping */ reg = snd_soc_read(codec, WM9081_VMID_CONTROL); - reg &= ~(WM9081_VMID_SEL_MASK | WM9081_BIAS_ENA); + reg &= ~WM9081_VMID_SEL_MASK; reg |= WM9081_VMID_RAMP; snd_soc_write(codec, WM9081_VMID_CONTROL, reg); -- cgit From dcaaf9f2c16b56f8bb316881fcd3f15c18fc71e7 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 8 Nov 2011 17:50:27 +0100 Subject: ALSA: usb-audio - Fix the missing volume quirks at delayed init In the recent usb-audio driver, the initialization of volume ranges may be delayed when the device doesn't respond well at the probing time. But the volume quirks for certain devices are applied only in mixer_ctl_feature_info() thus only at the very first probe and will be missing when the volume range is initialized later. This patch moves the volume quirk code to be always called from the volume-range extraction (get_min_max()), so that the quirks are properly applied in the later init time. Reported-and-tested-by: Alexey Fisher Cc: Signed-off-by: Takashi Iwai --- sound/usb/mixer.c | 109 +++++++++++++++++++++++++++++------------------------- 1 file changed, 59 insertions(+), 50 deletions(-) diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 60f65ace7474..c5444e00f0c6 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -765,10 +765,60 @@ static void usb_mixer_elem_free(struct snd_kcontrol *kctl) * 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, 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 */ -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 */ cval->min = default_min; @@ -844,6 +894,9 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min) cval->initialized = 1; } + if (kctl) + volume_control_quirks(cval, kctl); + /* USB descriptions contain the dB scale in 1/256 dB unit * while ALSA TLV contains in 1/100 dB unit */ @@ -864,6 +917,7 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min) return 0; } +#define get_min_max(cval, def) get_min_max_with_quirks(cval, def, NULL) /* get a feature/mixer unit info */ static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) @@ -882,7 +936,7 @@ static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol, struct snd_ctl_ uinfo->value.integer.max = 1; } else { if (!cval->initialized) { - get_min_max(cval, 0); + get_min_max_with_quirks(cval, 0, kcontrol); if (cval->initialized && cval->dBmin >= cval->dBmax) { kcontrol->vd[0].access &= ~(SNDRV_CTL_ELEM_ACCESS_TLV_READ | @@ -1045,9 +1099,6 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, 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 * read-only. set_cur_mix_value() will check the mask again and won't * issue write commands to read-only channels. */ @@ -1069,6 +1120,9 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, len = snd_usb_copy_string_desc(state, nameid, kctl->id.name, sizeof(kctl->id.name)); + /* get min/max values */ + get_min_max_with_quirks(cval, 0, kctl); + switch (control) { case UAC_FU_MUTE: case UAC_FU_VOLUME: @@ -1118,51 +1172,6 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, 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; /* 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 -- cgit From 8d1c963a2e0c57dfe7f9c356389902e500cf1cfd Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Tue, 8 Nov 2011 20:37:26 +0100 Subject: ALSA: HDA: Remove quirk for Toshiba T110 According to the bug reporter, model=auto is needed to make the internal microphone work. BugLink: https://bugs.launchpad.net/bugs/819699 Reported-by: Andrej (agno01) Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_conexant.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 5e706e4d1737..0de21193a2b0 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -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(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, 0xffe0, "Toshiba Satellite Pro T130-15F", CXT5066_OLPC_XO_1_5), SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board", CXT5066_LAPTOP), SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5), -- cgit 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 --- Documentation/sound/alsa/HD-Audio-Models.txt | 1 + sound/pci/hda/patch_sigmatel.c | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt index 4f3443230d89..edad99abec21 100644 --- a/Documentation/sound/alsa/HD-Audio-Models.txt +++ b/Documentation/sound/alsa/HD-Audio-Models.txt @@ -349,6 +349,7 @@ STAC92HD83* ref Reference board mic-ref Reference board with power management for ports dell-s14 Dell laptop + dell-vostro-3500 Dell Vostro 3500 laptop hp HP laptops with (inverted) mute-LED hp-dv7-4000 HP dv-7 4000 auto BIOS setup (default) 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 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(+) 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 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(-) 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 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(-) 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 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(-) 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 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(-) 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 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(-) 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 From 98d97019c88bd832da1457729739cf739ece493f Mon Sep 17 00:00:00 2001 From: Jassi Brar Date: Thu, 10 Nov 2011 17:19:07 +0530 Subject: MAINTAINERS: Drop inactive Samsung ASoC maintainer Signed-off-by: Jassi Brar Signed-off-by: Mark Brown --- MAINTAINERS | 1 - 1 file changed, 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index c802e5fa2d11..fd7e441b5ea7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5648,7 +5648,6 @@ F: drivers/media/video/*7146* F: include/media/*7146* SAMSUNG AUDIO (ASoC) DRIVERS -M: Jassi Brar M: Sangbeom Kim L: alsa-devel@alsa-project.org (moderated for non-subscribers) S: Supported -- cgit 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(-) 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 From afef2cfa0ecf45dec7e88db9fa312ee82d347111 Mon Sep 17 00:00:00 2001 From: Charles Chin Date: Fri, 11 Nov 2011 08:05:28 +0100 Subject: ALSA: hda - pwr_nids cleanup for IDT codecs Clean up and fix pwr_nids for 92HD71 / 73 / 83 family codecs; remove pwr_mapping which was incorrect. The original pwr_nids support of 92HD83xxx was incorrect and never actually worked before. Now we should have things working correctly without having to hack by DID anymore. It is also not necessary to explicitly turn on all the pins near the beginning of patch_stac92hd83xxx() now, the pins will go though initialization properly. Tested on 92HD66 / 71 / 73 / 75 / 83 / 89 / 91 demo boards. Signed-off-by: Charles Chin Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 33 +++++++++------------------------ 1 file changed, 9 insertions(+), 24 deletions(-) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index edc2b7bc177c..470f6f286e81 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -227,7 +227,6 @@ struct sigmatel_spec { /* power management */ unsigned int num_pwrs; - const unsigned int *pwr_mapping; const hda_nid_t *pwr_nids; const hda_nid_t *dac_list; @@ -374,18 +373,15 @@ static const unsigned long stac92hd73xx_capvols[] = { #define STAC92HD83_DAC_COUNT 3 -static const hda_nid_t stac92hd83xxx_pwr_nids[4] = { - 0xa, 0xb, 0xd, 0xe, +static const hda_nid_t stac92hd83xxx_pwr_nids[7] = { + 0x0a, 0x0b, 0x0c, 0xd, 0x0e, + 0x0f, 0x10 }; static const hda_nid_t stac92hd83xxx_slave_dig_outs[2] = { 0x1e, 0, }; -static const unsigned int stac92hd83xxx_pwr_mapping[4] = { - 0x03, 0x0c, 0x20, 0x40, -}; - static const hda_nid_t stac92hd83xxx_dmic_nids[] = { 0x11, 0x20, }; @@ -4470,8 +4466,12 @@ static int stac92xx_init(struct hda_codec *codec) stac_toggle_power_map(codec, nid, 1); continue; } - if (enable_pin_detect(codec, nid, STAC_PWR_EVENT)) + if (enable_pin_detect(codec, nid, STAC_PWR_EVENT)) { stac_issue_unsol_event(codec, nid); + continue; + } + /* none of the above, turn the port OFF */ + stac_toggle_power_map(codec, nid, 0); } /* sync mute LED */ @@ -4727,11 +4727,7 @@ static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid, if (idx >= spec->num_pwrs) return; - /* several codecs have two power down bits */ - if (spec->pwr_mapping) - idx = spec->pwr_mapping[idx]; - else - idx = 1 << idx; + idx = 1 << idx; val = snd_hda_codec_read(codec, codec->afg, 0, 0x0fec, 0x0) & 0xff; if (enable) @@ -5629,9 +5625,6 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) snd_hda_codec_set_pincfg(codec, 0xf, 0x2181205e); } - /* reset pin power-down; Windows may leave these bits after reboot */ - snd_hda_codec_write_cache(codec, codec->afg, 0, 0x7EC, 0); - snd_hda_codec_write_cache(codec, codec->afg, 0, 0x7ED, 0); codec->no_trigger_sense = 1; codec->spec = spec; @@ -5641,7 +5634,6 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) codec->slave_dig_outs = stac92hd83xxx_slave_dig_outs; spec->digbeep_nid = 0x21; spec->pwr_nids = stac92hd83xxx_pwr_nids; - spec->pwr_mapping = stac92hd83xxx_pwr_mapping; spec->num_pwrs = ARRAY_SIZE(stac92hd83xxx_pwr_nids); spec->multiout.dac_nids = spec->dac_nids; spec->init = stac92hd83xxx_core_init; @@ -5658,9 +5650,6 @@ again: stac92xx_set_config_regs(codec, stac92hd83xxx_brd_tbl[spec->board_config]); - if (spec->board_config != STAC_92HD83XXX_PWR_REF) - spec->num_pwrs = 0; - codec->patch_ops = stac92xx_patch_ops; if (find_mute_led_gpio(codec, 0)) @@ -5869,8 +5858,6 @@ again: (codec->revision_id & 0xf) == 1) spec->stream_delay = 40; /* 40 milliseconds */ - /* no output amps */ - spec->num_pwrs = 0; /* disable VSW */ spec->init = stac92hd71bxx_core_init; unmute_init++; @@ -5885,8 +5872,6 @@ again: if ((codec->revision_id & 0xf) == 1) spec->stream_delay = 40; /* 40 milliseconds */ - /* no output amps */ - spec->num_pwrs = 0; /* fallthru */ default: spec->init = stac92hd71bxx_core_init; -- cgit From e53de8f00c80fd1a312c95bc5157fdb98d46e070 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Sun, 13 Nov 2011 23:11:50 +0100 Subject: ALSA: hda/realtek: remove redundant semicolon Having just one semicolon after a break statement is enough. Signed-off-by: Jesper Juhl Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 308bb575bc06..336d14eb72af 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -1452,7 +1452,7 @@ static void alc_apply_fixup(struct hda_codec *codec, int action) switch (fix->type) { case ALC_FIXUP_SKU: if (action != ALC_FIXUP_ACT_PRE_PROBE || !fix->v.sku) - break;; + break; snd_printdd(KERN_INFO "hda_codec: %s: " "Apply sku override for %s\n", codec->chip_name, modelname); -- cgit From 54dc6cabe684375b3cf549c7b0545613d694aba8 Mon Sep 17 00:00:00 2001 From: Johannes Stezenbach Date: Mon, 14 Nov 2011 17:23:16 +0100 Subject: ASoC: sta32x: preserve coefficient RAM The coefficient RAM must be saved in a shadow so it can be restored when the codec is powered on using regulator_bulk_enable(). Signed-off-by: Johannes Stezenbach Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- sound/soc/codecs/sta32x.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++- sound/soc/codecs/sta32x.h | 1 + 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index bb82408ab8e1..d2f37152f940 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c @@ -76,6 +76,8 @@ struct sta32x_priv { unsigned int mclk; unsigned int format; + + u32 coef_shadow[STA32X_COEF_COUNT]; }; static const DECLARE_TLV_DB_SCALE(mvol_tlv, -12700, 50, 1); @@ -227,6 +229,7 @@ static int sta32x_coefficient_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); int numcoef = kcontrol->private_value >> 16; int index = kcontrol->private_value & 0xffff; unsigned int cfud; @@ -239,6 +242,11 @@ static int sta32x_coefficient_put(struct snd_kcontrol *kcontrol, snd_soc_write(codec, STA32X_CFUD, cfud); snd_soc_write(codec, STA32X_CFADDR2, index); + for (i = 0; i < numcoef && (index + i < STA32X_COEF_COUNT); i++) + sta32x->coef_shadow[index + i] = + (ucontrol->value.bytes.data[3 * i] << 16) + | (ucontrol->value.bytes.data[3 * i + 1] << 8) + | (ucontrol->value.bytes.data[3 * i + 2]); for (i = 0; i < 3 * numcoef; i++) snd_soc_write(codec, STA32X_B1CF1 + i, ucontrol->value.bytes.data[i]); @@ -252,6 +260,48 @@ static int sta32x_coefficient_put(struct snd_kcontrol *kcontrol, return 0; } +int sta32x_sync_coef_shadow(struct snd_soc_codec *codec) +{ + struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); + unsigned int cfud; + int i; + + /* preserve reserved bits in STA32X_CFUD */ + cfud = snd_soc_read(codec, STA32X_CFUD) & 0xf0; + + for (i = 0; i < STA32X_COEF_COUNT; i++) { + snd_soc_write(codec, STA32X_CFADDR2, i); + snd_soc_write(codec, STA32X_B1CF1, + (sta32x->coef_shadow[i] >> 16) & 0xff); + snd_soc_write(codec, STA32X_B1CF2, + (sta32x->coef_shadow[i] >> 8) & 0xff); + snd_soc_write(codec, STA32X_B1CF3, + (sta32x->coef_shadow[i]) & 0xff); + /* chip documentation does not say if the bits are + * self-clearing, so do it explicitly */ + snd_soc_write(codec, STA32X_CFUD, cfud); + snd_soc_write(codec, STA32X_CFUD, cfud | 0x01); + } + return 0; +} + +int sta32x_cache_sync(struct snd_soc_codec *codec) +{ + unsigned int mute; + int rc; + + if (!codec->cache_sync) + return 0; + + /* mute during register sync */ + mute = snd_soc_read(codec, STA32X_MMUTE); + snd_soc_write(codec, STA32X_MMUTE, mute | STA32X_MMUTE_MMUTE); + sta32x_sync_coef_shadow(codec); + rc = snd_soc_cache_sync(codec); + snd_soc_write(codec, STA32X_MMUTE, mute); + return rc; +} + #define SINGLE_COEF(xname, index) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .info = sta32x_coefficient_info, \ @@ -661,7 +711,7 @@ static int sta32x_set_bias_level(struct snd_soc_codec *codec, return ret; } - snd_soc_cache_sync(codec); + sta32x_cache_sync(codec); } /* Power up to mute */ @@ -790,6 +840,17 @@ static int sta32x_probe(struct snd_soc_codec *codec) STA32X_CxCFG_OM_MASK, 2 << STA32X_CxCFG_OM_SHIFT); + /* initialize coefficient shadow RAM with reset values */ + for (i = 4; i <= 49; i += 5) + sta32x->coef_shadow[i] = 0x400000; + for (i = 50; i <= 54; i++) + sta32x->coef_shadow[i] = 0x7fffff; + sta32x->coef_shadow[55] = 0x5a9df7; + sta32x->coef_shadow[56] = 0x7fffff; + sta32x->coef_shadow[59] = 0x7fffff; + sta32x->coef_shadow[60] = 0x400000; + sta32x->coef_shadow[61] = 0x400000; + sta32x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); /* Bias level configuration will have done an extra enable */ regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); diff --git a/sound/soc/codecs/sta32x.h b/sound/soc/codecs/sta32x.h index b97ee5a75667..d8e32a6262ee 100644 --- a/sound/soc/codecs/sta32x.h +++ b/sound/soc/codecs/sta32x.h @@ -19,6 +19,7 @@ /* STA326 register addresses */ #define STA32X_REGISTER_COUNT 0x2d +#define STA32X_COEF_COUNT 62 #define STA32X_CONFA 0x00 #define STA32X_CONFB 0x01 -- cgit From 0f768a7235d3dfb6f4833030a95a06419df089cb Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Mon, 14 Nov 2011 16:35:26 -0600 Subject: ASoC: fsl_ssi: properly initialize the sysfs attribute object Commit 6992f533 ("sysfs: Use one lockdep class per sysfs attribute") requires 'struct attribute' objects to be initialized with sysfs_attr_init(). Signed-off-by: Timur Tabi Signed-off-by: Mark Brown Cc: stable@kernel.org --- sound/soc/fsl/fsl_ssi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 0268cf989736..83c4bd5b2dd7 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -694,6 +694,7 @@ static int __devinit fsl_ssi_probe(struct platform_device *pdev) /* Initialize the the device_attribute structure */ dev_attr = &ssi_private->dev_attr; + sysfs_attr_init(&dev_attr->attr); dev_attr->attr.name = "statistics"; dev_attr->attr.mode = S_IRUGO; dev_attr->show = fsl_sysfs_ssi_show; -- cgit From b95d68b8179764e29558b75cec35ef4a6a98925b Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Wed, 16 Nov 2011 16:29:46 +0800 Subject: ALSA: hda - fix ELD memory leak memset(eld) clears eld->proc_entry which will leak the struct snd_info_entry when unloading module. Fix it by - memset only the fields before eld->eld_buffer - set eld->eld_valid to true _after_ all eld fields have been filled Cc: Cc: Pierre-louis Bossart Acked-by: Stephen Warren Signed-off-by: Wu Fengguang Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_eld.c | 5 +---- sound/pci/hda/hda_local.h | 3 +++ sound/pci/hda/patch_hdmi.c | 11 +++++------ 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c index 1c8ddf547a2d..a065d6d2d6ff 100644 --- a/sound/pci/hda/hda_eld.c +++ b/sound/pci/hda/hda_eld.c @@ -297,10 +297,10 @@ static int hdmi_update_eld(struct hdmi_eld *e, buf + ELD_FIXED_BYTES + mnl + 3 * i); } + e->eld_valid = true; return 0; out_fail: - e->eld_ver = 0; return -EINVAL; } @@ -323,9 +323,6 @@ int snd_hdmi_get_eld(struct hdmi_eld *eld, * ELD is valid, actual eld_size is assigned in hdmi_update_eld() */ - if (!eld->eld_valid) - return -ENOENT; - size = snd_hdmi_get_eld_size(codec, nid); if (size == 0) { /* wfg: workaround for ASUS P5E-VM HDMI board */ diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 6579e0f2bb57..618ddad17236 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h @@ -653,6 +653,9 @@ struct hdmi_eld { int spk_alloc; int sad_count; struct cea_sad sad[ELD_MAX_SAD]; + /* + * all fields above eld_buffer will be cleared before updating ELD + */ char eld_buffer[ELD_MAX_SIZE]; #ifdef CONFIG_PROC_FS struct snd_info_entry *proc_entry; diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 81b7b791b3c3..aebfee50bd88 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -980,20 +980,19 @@ static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid, * the unsolicited response to avoid custom WARs. */ int present = snd_hda_pin_sense(codec, pin_nid); + bool eld_valid = false; - memset(eld, 0, sizeof(*eld)); + memset(eld, 0, offsetof(struct hdmi_eld, eld_buffer)); eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE); if (eld->monitor_present) - eld->eld_valid = !!(present & AC_PINSENSE_ELDV); - else - eld->eld_valid = 0; + eld_valid = !!(present & AC_PINSENSE_ELDV); printk(KERN_INFO "HDMI status: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n", - codec->addr, pin_nid, eld->monitor_present, eld->eld_valid); + codec->addr, pin_nid, eld->monitor_present, eld_valid); - if (eld->eld_valid) + if (eld_valid) if (!snd_hdmi_get_eld(eld, codec, pin_nid)) snd_hdmi_show_eld(eld); -- cgit From 744626dada90cb1231a65b08874aa7a9f11c2ea8 Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Wed, 16 Nov 2011 16:29:47 +0800 Subject: ALSA: hda - delayed ELD repoll The Intel HDMI chips (ironlake at least) are found to have ~250ms delay between the ELD_Valid=1 hotplug event is send and the ELD buffer becomes actually readable. During the time the ELD buffer is mysteriously all 0. Fix it by scheduling a delayed work to re-read ELD buffer after 300ms. Signed-off-by: Wu Fengguang Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index aebfee50bd88..a76139b60154 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -65,7 +65,10 @@ struct hdmi_spec_per_pin { hda_nid_t pin_nid; int num_mux_nids; hda_nid_t mux_nids[HDA_MAX_CONNECTIONS]; + + struct hda_codec *codec; struct hdmi_eld sink_eld; + struct delayed_work work; }; struct hdmi_spec { @@ -745,8 +748,7 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, int pin_idx, * Unsolicited events */ -static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid, - struct hdmi_eld *eld); +static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, bool retry); static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) { @@ -766,7 +768,7 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) return; eld = &spec->pins[pin_idx].sink_eld; - hdmi_present_sense(codec, pin_nid, eld); + hdmi_present_sense(&spec->pins[pin_idx], true); /* * HDMI sink's ELD info cannot always be retrieved for now, e.g. @@ -968,9 +970,11 @@ static int hdmi_read_pin_conn(struct hda_codec *codec, int pin_idx) return 0; } -static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid, - struct hdmi_eld *eld) +static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, bool retry) { + struct hda_codec *codec = per_pin->codec; + struct hdmi_eld *eld = &per_pin->sink_eld; + hda_nid_t pin_nid = per_pin->pin_nid; /* * Always execute a GetPinSense verb here, even when called from * hdmi_intrinsic_event; for some NVIDIA HW, the unsolicited @@ -992,13 +996,27 @@ static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid, "HDMI status: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n", codec->addr, pin_nid, eld->monitor_present, eld_valid); - if (eld_valid) + if (eld_valid) { if (!snd_hdmi_get_eld(eld, codec, pin_nid)) snd_hdmi_show_eld(eld); + else if (retry) { + queue_delayed_work(codec->bus->workq, + &per_pin->work, + msecs_to_jiffies(300)); + } + } snd_hda_input_jack_report(codec, pin_nid); } +static void hdmi_repoll_eld(struct work_struct *work) +{ + struct hdmi_spec_per_pin *per_pin = + container_of(to_delayed_work(work), struct hdmi_spec_per_pin, work); + + hdmi_present_sense(per_pin, false); +} + static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) { struct hdmi_spec *spec = codec->spec; @@ -1227,7 +1245,7 @@ static int generic_hdmi_build_jack(struct hda_codec *codec, int pin_idx) if (err < 0) return err; - hdmi_present_sense(codec, per_pin->pin_nid, &per_pin->sink_eld); + hdmi_present_sense(per_pin, false); return 0; } @@ -1278,6 +1296,8 @@ static int generic_hdmi_init(struct hda_codec *codec) AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | pin_nid); + per_pin->codec = codec; + INIT_DELAYED_WORK(&per_pin->work, hdmi_repoll_eld); snd_hda_eld_proc_new(codec, eld, pin_idx); } return 0; @@ -1292,10 +1312,12 @@ static void generic_hdmi_free(struct hda_codec *codec) struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; struct hdmi_eld *eld = &per_pin->sink_eld; + cancel_delayed_work(&per_pin->work); snd_hda_eld_proc_free(codec, eld); } snd_hda_input_jack_free(codec); + flush_workqueue(codec->bus->workq); kfree(spec); } -- cgit From 2d1b439bdb3cee0ae5ccbd7f65e1e5852b1c2718 Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Wed, 16 Nov 2011 16:29:48 +0800 Subject: ALSA: hda - move eld->spk_alloc fixup to hdmi_update_eld() It looks more natural and saves two lines of code. Signed-off-by: Wu Fengguang Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_eld.c | 8 ++++++++ sound/pci/hda/patch_hdmi.c | 10 ---------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c index a065d6d2d6ff..7ae7578bdcc0 100644 --- a/sound/pci/hda/hda_eld.c +++ b/sound/pci/hda/hda_eld.c @@ -297,6 +297,14 @@ static int hdmi_update_eld(struct hdmi_eld *e, buf + ELD_FIXED_BYTES + mnl + 3 * i); } + /* + * HDMI sink's ELD info cannot always be retrieved for now, e.g. + * in console or for audio devices. Assume the highest speakers + * configuration, to _not_ prohibit multi-channel audio playback. + */ + if (!e->spk_alloc) + e->spk_alloc = 0xffff; + e->eld_valid = true; return 0; diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index a76139b60154..9850c5b481ea 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -757,7 +757,6 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) int pd = !!(res & AC_UNSOL_RES_PD); int eldv = !!(res & AC_UNSOL_RES_ELDV); int pin_idx; - struct hdmi_eld *eld; printk(KERN_INFO "HDMI hot plug event: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n", @@ -766,17 +765,8 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) pin_idx = pin_nid_to_pin_index(spec, pin_nid); if (pin_idx < 0) return; - eld = &spec->pins[pin_idx].sink_eld; hdmi_present_sense(&spec->pins[pin_idx], true); - - /* - * HDMI sink's ELD info cannot always be retrieved for now, e.g. - * in console or for audio devices. Assume the highest speakers - * configuration, to _not_ prohibit multi-channel audio playback. - */ - if (!eld->spk_alloc) - eld->spk_alloc = 0xffff; } static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res) -- cgit From 25d7d59d1f7321be85bda175c9a1bb85ca1b5881 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 16 Nov 2011 10:52:01 +0100 Subject: ALSA: hda - Update URLs in document Some stuff was moved from kernel.org to other places. Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/HD-Audio.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Documentation/sound/alsa/HD-Audio.txt b/Documentation/sound/alsa/HD-Audio.txt index 03e2771ddeef..91fee3b45fb8 100644 --- a/Documentation/sound/alsa/HD-Audio.txt +++ b/Documentation/sound/alsa/HD-Audio.txt @@ -579,7 +579,7 @@ Development Tree ~~~~~~~~~~~~~~~~ The latest development codes for HD-audio are found on sound git tree: -- git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6.git +- git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git The master branch or for-next branches can be used as the main development branches in general while the HD-audio specific patches @@ -594,7 +594,7 @@ is, installed via the usual spells: configure, make and make install(-modules). See INSTALL in the package. The snapshot tarballs are found at: -- ftp://ftp.kernel.org/pub/linux/kernel/people/tiwai/snapshot/ +- ftp://ftp.suse.com/pub/people/tiwai/snapshot/ Sending a Bug Report @@ -696,7 +696,7 @@ via hda-verb won't change the mixer value. The hda-verb program is found in the ftp directory: -- ftp://ftp.kernel.org/pub/linux/kernel/people/tiwai/misc/ +- ftp://ftp.suse.com/pub/people/tiwai/misc/ Also a git repository is available: @@ -764,7 +764,7 @@ operation, the jack plugging simulation, etc. The package is found in: -- ftp://ftp.kernel.org/pub/linux/kernel/people/tiwai/misc/ +- ftp://ftp.suse.com/pub/people/tiwai/misc/ A git repository is available: -- cgit From 05ee7964a470d29889ac48cc8274c1b5a1904a11 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 16 Nov 2011 18:05:11 +0100 Subject: ALSA: hda - Fix the connection selection of ADCs on Cirrus codecs spec->cur_adc isn't set until cs_capture_pcm_prepare() is called although the driver tries to select the connection at init time and at auto-mic switch. This results in the access to the widget NID 0, which is obviously invalid, also a wrong capture source. This patch fixes the issue by issuing the connect-select verb conditionally at appropriate places. Reported-and-tested-by: Dylan Reid Cc: Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_cirrus.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 2a2d8645ba09..2fbab8e29576 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c @@ -237,6 +237,15 @@ static int cs_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout); } +static void cs_update_input_select(struct hda_codec *codec) +{ + struct cs_spec *spec = codec->spec; + if (spec->cur_adc) + snd_hda_codec_write(codec, spec->cur_adc, 0, + AC_VERB_SET_CONNECT_SEL, + spec->adc_idx[spec->cur_input]); +} + /* * Analog capture */ @@ -250,6 +259,7 @@ static int cs_capture_pcm_prepare(struct hda_pcm_stream *hinfo, spec->cur_adc = spec->adc_nid[spec->cur_input]; spec->cur_adc_stream_tag = stream_tag; spec->cur_adc_format = format; + cs_update_input_select(codec); snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format); return 0; } @@ -689,10 +699,8 @@ static int change_cur_input(struct hda_codec *codec, unsigned int idx, spec->cur_adc_stream_tag, 0, spec->cur_adc_format); } - snd_hda_codec_write(codec, spec->cur_adc, 0, - AC_VERB_SET_CONNECT_SEL, - spec->adc_idx[idx]); spec->cur_input = idx; + cs_update_input_select(codec); return 1; } @@ -973,10 +981,7 @@ static void cs_automic(struct hda_codec *codec) } else { spec->cur_input = spec->last_input; } - - snd_hda_codec_write_cache(codec, spec->cur_adc, 0, - AC_VERB_SET_CONNECT_SEL, - spec->adc_idx[spec->cur_input]); + cs_update_input_select(codec); } else { if (present) change_cur_input(codec, spec->automic_idx, 0); @@ -1073,9 +1078,7 @@ static void init_input(struct hda_codec *codec) cs_automic(codec); else { spec->cur_adc = spec->adc_nid[spec->cur_input]; - snd_hda_codec_write(codec, spec->cur_adc, 0, - AC_VERB_SET_CONNECT_SEL, - spec->adc_idx[spec->cur_input]); + cs_update_input_select(codec); } } else { change_cur_input(codec, spec->cur_input, 1); -- cgit From 2391a0e06789a3f1718dee30b282562f7ed28c87 Mon Sep 17 00:00:00 2001 From: Timo Juhani Lindfors Date: Thu, 17 Nov 2011 02:52:50 +0200 Subject: ASoC: wm8753: Skip noop reconfiguration of DAI mode This patch makes it possible to set DAI mode to its currently applied value even if codec is active. This is necessary to allow aplay -t raw -r 44100 -f S16_LE -c 2 < /dev/urandom & alsactl store -f backup.state alsactl restore -f backup.state to work without returning errors. This patch is based on a patch sent by Klaus Kurzmann . Signed-off-by: Timo Juhani Lindfors Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- sound/soc/codecs/wm8753.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index a9504710bb69..3a629d0d690e 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c @@ -190,6 +190,9 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol, struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); u16 ioctl; + if (wm8753->dai_func == ucontrol->value.integer.value[0]) + return 0; + if (codec->active) return -EBUSY; -- cgit From dbd1b5473ce8ae40fe7385eacc9294355eec0676 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sat, 19 Nov 2011 11:41:30 +0100 Subject: ALSA: hda - Add pin fix for Alienware M17x R3 Reported-by: Albert Pool Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 470f6f286e81..f3658658548e 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -1641,6 +1641,8 @@ static const struct snd_pci_quirk stac92hd73xx_codec_id_cfg_tbl[] = { "Alienware M17x", STAC_ALIENWARE_M17X), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x043a, "Alienware M17x", STAC_ALIENWARE_M17X), + SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0490, + "Alienware M17x", STAC_ALIENWARE_M17X), {} /* terminator */ }; -- cgit From 0aed4a95ce3b39acfceb38ab7f93c7906b4a27f8 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Sun, 20 Nov 2011 15:10:27 +0100 Subject: ASoC: adau1373: fix DB_RANGE size Give the correct number of entries to TLV_DB_RANGE_HEAD to prevent reading more data than actually is in the array. Signed-off-by: Clemens Ladisch --- sound/soc/codecs/adau1373.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c index 1ccf8dd47576..45c63028b40d 100644 --- a/sound/soc/codecs/adau1373.c +++ b/sound/soc/codecs/adau1373.c @@ -245,7 +245,7 @@ static const char *adau1373_bass_hpf_cutoff_text[] = { }; static const unsigned int adau1373_bass_tlv[] = { - TLV_DB_RANGE_HEAD(4), + TLV_DB_RANGE_HEAD(3), 0, 2, TLV_DB_SCALE_ITEM(-600, 600, 1), 3, 4, TLV_DB_SCALE_ITEM(950, 250, 0), 5, 7, TLV_DB_SCALE_ITEM(1400, 150, 0), -- cgit From a19ea0b8ec1f6892bf18f461d5023c9299e1417b Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Sun, 20 Nov 2011 15:11:54 +0100 Subject: ASoC: rt5631: fix DB_RANGE size Give the correct number of entries to TLV_DB_RANGE_HEAD to prevent the last entry from being omitted. Signed-off-by: Clemens Ladisch --- sound/soc/codecs/rt5631.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c index 27a078cbb6eb..4646e808b90a 100644 --- a/sound/soc/codecs/rt5631.c +++ b/sound/soc/codecs/rt5631.c @@ -177,7 +177,7 @@ static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -95625, 375, 0); static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0); /* {0, +20, +24, +30, +35, +40, +44, +50, +52}dB */ static unsigned int mic_bst_tlv[] = { - TLV_DB_RANGE_HEAD(6), + TLV_DB_RANGE_HEAD(7), 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), 1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0), 2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0), -- cgit From 740fb9d512d91b1d6192ea13c109efa05b101424 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Sun, 20 Nov 2011 15:12:26 +0100 Subject: ASoC: sgtl5000: fix DB_RANGE size Give the correct number of entries to TLV_DB_RANGE_HEAD to prevent reading more data than actually is in the array. Signed-off-by: Clemens Ladisch --- sound/soc/codecs/sgtl5000.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index d15695d1c273..bbcf921166f7 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -365,7 +365,7 @@ static const DECLARE_TLV_DB_SCALE(capture_6db_attenuate, -600, 600, 0); /* tlv for mic gain, 0db 20db 30db 40db */ static const unsigned int mic_gain_tlv[] = { - TLV_DB_RANGE_HEAD(4), + TLV_DB_RANGE_HEAD(2), 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), 1, 3, TLV_DB_SCALE_ITEM(2000, 1000, 0), }; -- cgit From 43e9dc7bce9f21355cd2aa493a99281eae03b156 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Sun, 20 Nov 2011 15:13:27 +0100 Subject: ASoC: wm8962: fix DB_RANGE size Give the correct number of entries to TLV_DB_RANGE_HEAD to prevent reading more data than actually is in the arrays. Signed-off-by: Clemens Ladisch --- sound/soc/codecs/wm8962.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 91d3c6dbeba3..53edd9a8c758 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -1973,7 +1973,7 @@ static int wm8962_reset(struct snd_soc_codec *codec) static const DECLARE_TLV_DB_SCALE(inpga_tlv, -2325, 75, 0); static const DECLARE_TLV_DB_SCALE(mixin_tlv, -1500, 300, 0); static const unsigned int mixinpga_tlv[] = { - TLV_DB_RANGE_HEAD(7), + TLV_DB_RANGE_HEAD(5), 0, 1, TLV_DB_SCALE_ITEM(0, 600, 0), 2, 2, TLV_DB_SCALE_ITEM(1300, 1300, 0), 3, 4, TLV_DB_SCALE_ITEM(1800, 200, 0), @@ -1988,7 +1988,7 @@ static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0); static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1); static const DECLARE_TLV_DB_SCALE(hp_tlv, -700, 100, 0); static const unsigned int classd_tlv[] = { - TLV_DB_RANGE_HEAD(7), + TLV_DB_RANGE_HEAD(2), 0, 6, TLV_DB_SCALE_ITEM(0, 150, 0), 7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0), }; -- cgit From dac678f5c281fac55aadfa5f390c12a8d14bbc67 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Sun, 20 Nov 2011 15:14:11 +0100 Subject: ASoC: wm8993: fix DB_RANGE size Give the correct number of entries to TLV_DB_RANGE_HEAD to prevent reading more data than actually is in the array. Signed-off-by: Clemens Ladisch --- sound/soc/codecs/wm8993.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index eec8e1435116..d1a142f48b09 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c @@ -512,7 +512,7 @@ static const DECLARE_TLV_DB_SCALE(drc_comp_threash, -4500, 75, 0); static const DECLARE_TLV_DB_SCALE(drc_comp_amp, -2250, 75, 0); static const DECLARE_TLV_DB_SCALE(drc_min_tlv, -1800, 600, 0); static const unsigned int drc_max_tlv[] = { - TLV_DB_RANGE_HEAD(4), + TLV_DB_RANGE_HEAD(2), 0, 2, TLV_DB_SCALE_ITEM(1200, 600, 0), 3, 3, TLV_DB_SCALE_ITEM(3600, 0, 0), }; -- cgit From a1320fee27352b608a82020a47a59bb15e6e5db8 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Sun, 20 Nov 2011 15:14:55 +0100 Subject: ASoC: wm9090: fix DB_RANGE size Give the correct number of entries to TLV_DB_RANGE_HEAD to prevent reading more data than actually is in the arrays. Signed-off-by: Clemens Ladisch --- sound/soc/codecs/wm9090.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c index 2b5252c9e377..f94c06057c64 100644 --- a/sound/soc/codecs/wm9090.c +++ b/sound/soc/codecs/wm9090.c @@ -177,19 +177,19 @@ static void wait_for_dc_servo(struct snd_soc_codec *codec) } static const unsigned int in_tlv[] = { - TLV_DB_RANGE_HEAD(6), + TLV_DB_RANGE_HEAD(3), 0, 0, TLV_DB_SCALE_ITEM(-600, 0, 0), 1, 3, TLV_DB_SCALE_ITEM(-350, 350, 0), 4, 6, TLV_DB_SCALE_ITEM(600, 600, 0), }; static const unsigned int mix_tlv[] = { - TLV_DB_RANGE_HEAD(4), + TLV_DB_RANGE_HEAD(2), 0, 2, TLV_DB_SCALE_ITEM(-1200, 300, 0), 3, 3, TLV_DB_SCALE_ITEM(0, 0, 0), }; static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0); static const unsigned int spkboost_tlv[] = { - TLV_DB_RANGE_HEAD(7), + TLV_DB_RANGE_HEAD(2), 0, 6, TLV_DB_SCALE_ITEM(0, 150, 0), 7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0), }; -- cgit From 028aa634e180107ac93b790c0fed7376c0402d1a Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Sun, 20 Nov 2011 15:15:31 +0100 Subject: ASoC: wm_hubs: fix DB_RANGE size Give the correct number of entries to TLV_DB_RANGE_HEAD to prevent reading more data than actually is in the array. Signed-off-by: Clemens Ladisch --- sound/soc/codecs/wm_hubs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index 84f33d4ea2cd..48e61e912400 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -40,7 +40,7 @@ static const DECLARE_TLV_DB_SCALE(outmix_tlv, -2100, 300, 0); static const DECLARE_TLV_DB_SCALE(spkmixout_tlv, -1800, 600, 1); static const DECLARE_TLV_DB_SCALE(outpga_tlv, -5700, 100, 0); static const unsigned int spkboost_tlv[] = { - TLV_DB_RANGE_HEAD(7), + TLV_DB_RANGE_HEAD(2), 0, 6, TLV_DB_SCALE_ITEM(0, 150, 0), 7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0), }; -- cgit From ef0cd47093a6c4b8a1f17d7be02a966f7805ff41 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 19 Nov 2011 14:41:07 +0800 Subject: ASoC: cs4271: Fix wrong mask parameter in some snd_soc_update_bits calls Signed-off-by: Axel Lin Acked-by: Alexander Sverdlin Signed-off-by: Mark Brown --- sound/soc/codecs/cs4271.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c index 23d1bd5dadda..69fde1506fe1 100644 --- a/sound/soc/codecs/cs4271.c +++ b/sound/soc/codecs/cs4271.c @@ -434,7 +434,8 @@ static int cs4271_soc_suspend(struct snd_soc_codec *codec, pm_message_t mesg) { int ret; /* Set power-down bit */ - ret = snd_soc_update_bits(codec, CS4271_MODE2, 0, CS4271_MODE2_PDN); + ret = snd_soc_update_bits(codec, CS4271_MODE2, CS4271_MODE2_PDN, + CS4271_MODE2_PDN); if (ret < 0) return ret; return 0; @@ -501,8 +502,9 @@ static int cs4271_probe(struct snd_soc_codec *codec) return ret; } - ret = snd_soc_update_bits(codec, CS4271_MODE2, 0, - CS4271_MODE2_PDN | CS4271_MODE2_CPEN); + ret = snd_soc_update_bits(codec, CS4271_MODE2, + CS4271_MODE2_PDN | CS4271_MODE2_CPEN, + CS4271_MODE2_PDN | CS4271_MODE2_CPEN); if (ret < 0) return ret; ret = snd_soc_update_bits(codec, CS4271_MODE2, CS4271_MODE2_PDN, 0); -- cgit From 27533df80e93dc164e39d47281bbbd608f9014a6 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sun, 20 Nov 2011 23:57:49 +0300 Subject: ALSA: cs5535 - Fix an endianness conversion desc->size is supposed to be a le16 type. On a big endian system the current code will set ->size to zero. We fixed a similar bug on the next line but missed this one. Signed-off-by: Dan Carpenter Signed-off-by: Takashi Iwai --- sound/pci/cs5535audio/cs5535audio_pcm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/cs5535audio/cs5535audio_pcm.c b/sound/pci/cs5535audio/cs5535audio_pcm.c index e083122ca55a..dbf94b189e75 100644 --- a/sound/pci/cs5535audio/cs5535audio_pcm.c +++ b/sound/pci/cs5535audio/cs5535audio_pcm.c @@ -148,7 +148,7 @@ static int cs5535audio_build_dma_packets(struct cs5535audio *cs5535au, struct cs5535audio_dma_desc *desc = &((struct cs5535audio_dma_desc *) dma->desc_buf.area)[i]; desc->addr = cpu_to_le32(addr); - desc->size = cpu_to_le32(period_bytes); + desc->size = cpu_to_le16(period_bytes); desc->ctlreserved = cpu_to_le16(PRD_EOP); desc_addr += sizeof(struct cs5535audio_dma_desc); addr += period_bytes; -- cgit From ed3e80c4c991a52f9fce3421536a78e331ae0949 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 21 Nov 2011 11:55:41 +0000 Subject: ASoC: Ensure WM8731 register cache is synced when resuming from disabled Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- sound/soc/codecs/wm8731.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index 7e5ec03f6f8d..a7c9ae17fc7e 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c @@ -453,6 +453,7 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec, snd_soc_write(codec, WM8731_PWR, 0xffff); regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); + codec->cache_sync = 1; break; } codec->dapm.bias_level = level; -- cgit From 05c7cc9ccab7d9229fdae68d7d6231edd2c93741 Mon Sep 17 00:00:00 2001 From: Adrian Knoth Date: Mon, 21 Nov 2011 16:15:36 +0100 Subject: ALSA: hdspm - Fix PCI ID for PCIe RME MADI cards Commit c09403dcc5698abf214329fbbf3cf8dbb5558bea has introduced a regression: PCIe versions of RME MADI were no longer detected, because the MADIface ID (0xd5) was used instead of the correct 0xd2. This commit fixes the problem. Signed-off-by: Adrian Knoth Signed-off-by: Takashi Iwai --- sound/pci/rme9652/hdspm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index e760adad9523..19ee2203cbb5 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -6518,7 +6518,7 @@ static int __devinit snd_hdspm_create(struct snd_card *card, hdspm->io_type = AES32; hdspm->card_name = "RME AES32"; hdspm->midiPorts = 2; - } else if ((hdspm->firmware_rev == 0xd5) || + } else if ((hdspm->firmware_rev == 0xd2) || ((hdspm->firmware_rev >= 0xc8) && (hdspm->firmware_rev <= 0xcf))) { hdspm->io_type = MADI; -- cgit From c6e8453e7511001e453f8b20b9ceefd231946867 Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Fri, 18 Nov 2011 16:59:32 -0600 Subject: ALSA: hda - repoll ELD content for multiple times Improve the one-shot ELD repoll to up to 6 retries. Up to now the 300ms looks sufficient for the test boxes. However I'm a bit worried about how well it can fit the wider user base. Signed-off-by: Wu Fengguang Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 9850c5b481ea..c505fd5d338c 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -69,6 +69,7 @@ struct hdmi_spec_per_pin { struct hda_codec *codec; struct hdmi_eld sink_eld; struct delayed_work work; + int repoll_count; }; struct hdmi_spec { @@ -748,7 +749,7 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, int pin_idx, * Unsolicited events */ -static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, bool retry); +static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll); static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) { @@ -766,7 +767,7 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) if (pin_idx < 0) return; - hdmi_present_sense(&spec->pins[pin_idx], true); + hdmi_present_sense(&spec->pins[pin_idx], 1); } static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res) @@ -960,7 +961,7 @@ static int hdmi_read_pin_conn(struct hda_codec *codec, int pin_idx) return 0; } -static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, bool retry) +static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll) { struct hda_codec *codec = per_pin->codec; struct hdmi_eld *eld = &per_pin->sink_eld; @@ -989,7 +990,7 @@ static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, bool retry) if (eld_valid) { if (!snd_hdmi_get_eld(eld, codec, pin_nid)) snd_hdmi_show_eld(eld); - else if (retry) { + else if (repoll) { queue_delayed_work(codec->bus->workq, &per_pin->work, msecs_to_jiffies(300)); @@ -1004,7 +1005,10 @@ static void hdmi_repoll_eld(struct work_struct *work) struct hdmi_spec_per_pin *per_pin = container_of(to_delayed_work(work), struct hdmi_spec_per_pin, work); - hdmi_present_sense(per_pin, false); + if (per_pin->repoll_count++ > 6) + per_pin->repoll_count = 0; + + hdmi_present_sense(per_pin, per_pin->repoll_count); } static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) @@ -1235,7 +1239,7 @@ static int generic_hdmi_build_jack(struct hda_codec *codec, int pin_idx) if (err < 0) return err; - hdmi_present_sense(per_pin, false); + hdmi_present_sense(per_pin, 0); return 0; } -- cgit From afd00d7235c1989d06d75cf8ac3d7722fcf2f394 Mon Sep 17 00:00:00 2001 From: Tim Blechmann Date: Tue, 22 Nov 2011 11:15:44 +0100 Subject: ALSA: lx6464es - command buffer API cleanup the command buffer is only accessed from one file, so we can declare the specific functions as static in that file Signed-off-by: Tim Blechmann Signed-off-by: Takashi Iwai --- sound/pci/lx6464es/lx_core.c | 7 ++++--- sound/pci/lx6464es/lx_core.h | 3 --- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/sound/pci/lx6464es/lx_core.c b/sound/pci/lx6464es/lx_core.c index 5c8717e29eeb..ad52f4187e40 100644 --- a/sound/pci/lx6464es/lx_core.c +++ b/sound/pci/lx6464es/lx_core.c @@ -78,7 +78,8 @@ unsigned long lx_dsp_reg_read(struct lx6464es *chip, int port) return ioread32(address); } -void lx_dsp_reg_readbuf(struct lx6464es *chip, int port, u32 *data, u32 len) +static void lx_dsp_reg_readbuf(struct lx6464es *chip, int port, u32 *data, + u32 len) { void __iomem *address = lx_dsp_register(chip, port); memcpy_fromio(data, address, len*sizeof(u32)); @@ -91,8 +92,8 @@ void lx_dsp_reg_write(struct lx6464es *chip, int port, unsigned data) iowrite32(data, address); } -void lx_dsp_reg_writebuf(struct lx6464es *chip, int port, const u32 *data, - u32 len) +static void lx_dsp_reg_writebuf(struct lx6464es *chip, int port, + const u32 *data, u32 len) { void __iomem *address = lx_dsp_register(chip, port); memcpy_toio(address, data, len*sizeof(u32)); diff --git a/sound/pci/lx6464es/lx_core.h b/sound/pci/lx6464es/lx_core.h index 1dd562980b6c..4d7ff797a646 100644 --- a/sound/pci/lx6464es/lx_core.h +++ b/sound/pci/lx6464es/lx_core.h @@ -72,10 +72,7 @@ enum { }; unsigned long lx_dsp_reg_read(struct lx6464es *chip, int port); -void lx_dsp_reg_readbuf(struct lx6464es *chip, int port, u32 *data, u32 len); void lx_dsp_reg_write(struct lx6464es *chip, int port, unsigned data); -void lx_dsp_reg_writebuf(struct lx6464es *chip, int port, const u32 *data, - u32 len); /* plx register access */ enum { -- cgit From a29878553a9a7b4c06f93c7e383527cf014d4ceb Mon Sep 17 00:00:00 2001 From: Tim Blechmann Date: Tue, 22 Nov 2011 11:15:45 +0100 Subject: ALSA: lx6464es - fix device communication via command bus commit 6175ddf06b6172046a329e3abfd9c901a43efd2e optimized the mem*io functions that have been used to send commands to the device. these optimizations somehow corrupted the communication with the lx6464es, that resulted the device to be unusable with kernels after 2.6.33. this patch emulates the memcpy_*_io functions via a loop to avoid these problems. Signed-off-by: Tim Blechmann LKML-Reference: <4ECB5257.4040600@ladisch.de> Cc: Signed-off-by: Takashi Iwai --- sound/pci/lx6464es/lx_core.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/sound/pci/lx6464es/lx_core.c b/sound/pci/lx6464es/lx_core.c index ad52f4187e40..8c3e7fcefd99 100644 --- a/sound/pci/lx6464es/lx_core.c +++ b/sound/pci/lx6464es/lx_core.c @@ -81,8 +81,12 @@ unsigned long lx_dsp_reg_read(struct lx6464es *chip, int port) static void lx_dsp_reg_readbuf(struct lx6464es *chip, int port, u32 *data, u32 len) { - void __iomem *address = lx_dsp_register(chip, port); - memcpy_fromio(data, address, len*sizeof(u32)); + u32 __iomem *address = lx_dsp_register(chip, port); + int i; + + /* we cannot use memcpy_fromio */ + for (i = 0; i != len; ++i) + data[i] = ioread32(address + i); } @@ -95,8 +99,12 @@ void lx_dsp_reg_write(struct lx6464es *chip, int port, unsigned data) static void lx_dsp_reg_writebuf(struct lx6464es *chip, int port, const u32 *data, u32 len) { - void __iomem *address = lx_dsp_register(chip, port); - memcpy_toio(address, data, len*sizeof(u32)); + u32 __iomem *address = lx_dsp_register(chip, port); + int i; + + /* we cannot use memcpy_to */ + for (i = 0; i != len; ++i) + iowrite32(data[i], address + i); } -- cgit From a370fc62b9ad3f73abe2a721de6c03cdcce95b54 Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Tue, 22 Nov 2011 16:46:23 +0800 Subject: ALSA: hda - fail ELD reading early With the ELD repoll mechanism, we can (and should) fail the ELD reading immediately when find something obviously wrong and let the caller retry after some delay. Signed-off-by: Wu Fengguang Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_eld.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c index 7ae7578bdcc0..c1da422e085a 100644 --- a/sound/pci/hda/hda_eld.c +++ b/sound/pci/hda/hda_eld.c @@ -347,18 +347,28 @@ int snd_hdmi_get_eld(struct hdmi_eld *eld, for (i = 0; i < size; i++) { unsigned int val = hdmi_get_eld_data(codec, nid, i); + /* + * Graphics driver might be writing to ELD buffer right now. + * Just abort. The caller will repoll after a while. + */ if (!(val & AC_ELDD_ELD_VALID)) { - if (!i) { - snd_printd(KERN_INFO - "HDMI: invalid ELD data\n"); - ret = -EINVAL; - goto error; - } snd_printd(KERN_INFO "HDMI: invalid ELD data byte %d\n", i); - val = 0; - } else - val &= AC_ELDD_ELD_DATA; + ret = -EINVAL; + goto error; + } + val &= AC_ELDD_ELD_DATA; + /* + * The first byte cannot be zero. This can happen on some DVI + * connections. Some Intel chips may also need some 250ms delay + * to return non-zero ELD data, even when the graphics driver + * correctly writes ELD content before setting ELD_valid bit. + */ + if (!val && !i) { + snd_printdd(KERN_INFO "HDMI: 0 ELD data\n"); + ret = -EINVAL; + goto error; + } buf[i] = val; } -- cgit From 72531c9434fa884d20cb3c36fcec83752f32fdf4 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 22 Nov 2011 09:46:51 +0800 Subject: ASoC: Fix wrong define for AD1836_ADC_WORD_OFFSET According to the datasheet: The BIT[5:4] of ADC Control Register 2 is to control the word width. 00 = 25 Bits 01 = 20 Bits 10 = 16 Bits 11 = Invalid Thus, the AD1836_ADC_WORD_OFFSET should be defined as 4. Signed-off-by: Axel Lin Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- sound/soc/codecs/ad1836.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/ad1836.h b/sound/soc/codecs/ad1836.h index 444747f0db26..dd7be0dbbc58 100644 --- a/sound/soc/codecs/ad1836.h +++ b/sound/soc/codecs/ad1836.h @@ -34,7 +34,7 @@ #define AD1836_ADC_CTRL2 13 #define AD1836_ADC_WORD_LEN_MASK 0x30 -#define AD1836_ADC_WORD_OFFSET 5 +#define AD1836_ADC_WORD_OFFSET 4 #define AD1836_ADC_SERFMT_MASK (7 << 6) #define AD1836_ADC_SERFMT_PCK256 (0x4 << 6) #define AD1836_ADC_SERFMT_PCK128 (0x5 << 6) -- cgit From 5c4b2aa3fd1dc30af098de5dec766a817621ace2 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 22 Nov 2011 14:47:44 +0800 Subject: ASoC: max9877: Update register if either val or val2 is changed In the case of ((max9877_regs[reg] >> shift) & mask) != val but ((max9877_regs[reg2] >> shift) & mask) == val2, current code does not update the registers. Fix the logic to update registers if either val or val2 is changed. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- sound/soc/codecs/max9877.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/max9877.c b/sound/soc/codecs/max9877.c index 9e7e964a5fa3..dcf6f2a1600a 100644 --- a/sound/soc/codecs/max9877.c +++ b/sound/soc/codecs/max9877.c @@ -106,13 +106,13 @@ static int max9877_set_2reg(struct snd_kcontrol *kcontrol, unsigned int mask = mc->max; unsigned int val = (ucontrol->value.integer.value[0] & mask); unsigned int val2 = (ucontrol->value.integer.value[1] & mask); - unsigned int change = 1; + unsigned int change = 0; - if (((max9877_regs[reg] >> shift) & mask) == val) - change = 0; + if (((max9877_regs[reg] >> shift) & mask) != val) + change = 1; - if (((max9877_regs[reg2] >> shift) & mask) == val2) - change = 0; + if (((max9877_regs[reg2] >> shift) & mask) != val2) + change = 1; if (change) { max9877_regs[reg] &= ~(mask << shift); -- cgit From 3d94a2a53a3979c30620e3adea10f20bef8267b3 Mon Sep 17 00:00:00 2001 From: Boojin Kim Date: Tue, 22 Nov 2011 11:03:22 +0900 Subject: ASoC: SAMSUNG: Fix build error This patch adds to fix following build errors. sound/soc/codecs/wm8994.c: In function 'wm8994_readable': sound/soc/codecs/wm8994.c:58: warning: unused variable 'wm8994' sound/soc/samsung/smdk_wm8994.c:176: error: expected declaration specifiers or '...' before string constant sound/soc/samsung/smdk_wm8994.c:176: warning: data definition has no type or storage class sound/soc/samsung/smdk_wm8994.c:176: warning: type defaults to 'int' in declaration of 'MODULE_DESCRIPTION' sound/soc/samsung/smdk_wm8994.c:176: warning: function declaration isn't a prototype sound/soc/samsung/smdk_wm8994.c:177: error: expected declaration specifiers or '...' before string constant Signed-off-by: Boojin Kim Signed-off-by: Mark Brown --- sound/soc/samsung/smdk_wm8994.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/samsung/smdk_wm8994.c b/sound/soc/samsung/smdk_wm8994.c index f75e43997d5b..ad9ac42522e2 100644 --- a/sound/soc/samsung/smdk_wm8994.c +++ b/sound/soc/samsung/smdk_wm8994.c @@ -9,6 +9,7 @@ #include "../codecs/wm8994.h" #include +#include /* * Default CFG switch settings to use this driver: -- cgit From d66b8537b30fbaf79e0f467fa6b7e1a2191cba83 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Tue, 22 Nov 2011 17:17:23 +0100 Subject: ASoC: cs4720: use snd_soc_cache_sync() Replace the manual register restore mechanism in cs4270.c and call the generic snd_soc_cache_sync() handler instead. This factors code out in favour of core facilities and also fixes a bus confusion that is most probably caused by intermixing i2c-regmap functions and i2c_smbus_* accessors. Signed-off-by: Daniel Mack Reported-and-tested-by: Sven Neumann Acked-by: Timur Tabi Signed-off-by: Mark Brown --- sound/soc/codecs/cs4270.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index f1f237ecec2a..73f46eb459f1 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -601,7 +601,6 @@ static int cs4270_soc_suspend(struct snd_soc_codec *codec, pm_message_t mesg) static int cs4270_soc_resume(struct snd_soc_codec *codec) { struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); - struct i2c_client *i2c_client = to_i2c_client(codec->dev); int reg; regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies), @@ -612,14 +611,7 @@ static int cs4270_soc_resume(struct snd_soc_codec *codec) ndelay(500); /* first restore the entire register cache ... */ - for (reg = CS4270_FIRSTREG; reg <= CS4270_LASTREG; reg++) { - u8 val = snd_soc_read(codec, reg); - - if (i2c_smbus_write_byte_data(i2c_client, reg, val)) { - dev_err(codec->dev, "i2c write failed\n"); - return -EIO; - } - } + snd_soc_cache_sync(codec); /* ... then disable the power-down bits */ reg = snd_soc_read(codec, CS4270_PWRCTL); -- cgit From 380c88303812951f6c838241366a66a03fb5c897 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Tue, 22 Nov 2011 14:38:59 -0600 Subject: ASoC: mpc8610: tell the CS4270 codec that it's the master Commit ac601555 ("ASoC: Return early with -EINVAL if invalid dai format is detected") requires the machine driver to tell the CS4270 codec driver whether the CS4270 should be configured for master or slave operation. Signed-off-by: Timur Tabi Signed-off-by: Mark Brown --- sound/soc/fsl/mpc8610_hpcd.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c index 31af405bda84..ae49f1c78c6d 100644 --- a/sound/soc/fsl/mpc8610_hpcd.c +++ b/sound/soc/fsl/mpc8610_hpcd.c @@ -392,7 +392,8 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev) } if (strcasecmp(sprop, "i2s-slave") == 0) { - machine_data->dai_format = SND_SOC_DAIFMT_I2S; + machine_data->dai_format = + SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM; machine_data->codec_clk_direction = SND_SOC_CLOCK_OUT; machine_data->cpu_clk_direction = SND_SOC_CLOCK_IN; @@ -409,31 +410,38 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev) } machine_data->clk_frequency = be32_to_cpup(iprop); } else if (strcasecmp(sprop, "i2s-master") == 0) { - machine_data->dai_format = SND_SOC_DAIFMT_I2S; + machine_data->dai_format = + SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS; machine_data->codec_clk_direction = SND_SOC_CLOCK_IN; machine_data->cpu_clk_direction = SND_SOC_CLOCK_OUT; } else if (strcasecmp(sprop, "lj-slave") == 0) { - machine_data->dai_format = SND_SOC_DAIFMT_LEFT_J; + machine_data->dai_format = + SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBM_CFM; machine_data->codec_clk_direction = SND_SOC_CLOCK_OUT; machine_data->cpu_clk_direction = SND_SOC_CLOCK_IN; } else if (strcasecmp(sprop, "lj-master") == 0) { - machine_data->dai_format = SND_SOC_DAIFMT_LEFT_J; + machine_data->dai_format = + SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBS_CFS; machine_data->codec_clk_direction = SND_SOC_CLOCK_IN; machine_data->cpu_clk_direction = SND_SOC_CLOCK_OUT; } else if (strcasecmp(sprop, "rj-slave") == 0) { - machine_data->dai_format = SND_SOC_DAIFMT_RIGHT_J; + machine_data->dai_format = + SND_SOC_DAIFMT_RIGHT_J | SND_SOC_DAIFMT_CBM_CFM; machine_data->codec_clk_direction = SND_SOC_CLOCK_OUT; machine_data->cpu_clk_direction = SND_SOC_CLOCK_IN; } else if (strcasecmp(sprop, "rj-master") == 0) { - machine_data->dai_format = SND_SOC_DAIFMT_RIGHT_J; + machine_data->dai_format = + SND_SOC_DAIFMT_RIGHT_J | SND_SOC_DAIFMT_CBS_CFS; machine_data->codec_clk_direction = SND_SOC_CLOCK_IN; machine_data->cpu_clk_direction = SND_SOC_CLOCK_OUT; } else if (strcasecmp(sprop, "ac97-slave") == 0) { - machine_data->dai_format = SND_SOC_DAIFMT_AC97; + machine_data->dai_format = + SND_SOC_DAIFMT_AC97 | SND_SOC_DAIFMT_CBM_CFM; machine_data->codec_clk_direction = SND_SOC_CLOCK_OUT; machine_data->cpu_clk_direction = SND_SOC_CLOCK_IN; } else if (strcasecmp(sprop, "ac97-master") == 0) { - machine_data->dai_format = SND_SOC_DAIFMT_AC97; + machine_data->dai_format = + SND_SOC_DAIFMT_AC97 | SND_SOC_DAIFMT_CBS_CFS; machine_data->codec_clk_direction = SND_SOC_CLOCK_IN; machine_data->cpu_clk_direction = SND_SOC_CLOCK_OUT; } else { -- cgit From e2301a4de22c438f5a962c7cefc3e9cba736991c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 22 Nov 2011 19:58:56 +0100 Subject: ALSA: hda - Check subdevice mask in snd_hda_check_board_codec_sid_config() In snd_hda_check_board_codec_sid_config(), not only comparing with the exact value but allow the bit-mask comparison for vendor-only, etc. Tested-by: Linus Torvalds Tested-by: Dirk Hohndel Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index e44b107fdc75..4562e9de6a1a 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -4046,9 +4046,9 @@ int snd_hda_check_board_codec_sid_config(struct hda_codec *codec, /* Search for codec ID */ for (q = tbl; q->subvendor; q++) { - unsigned long vendorid = (q->subdevice) | (q->subvendor << 16); - - if (vendorid == codec->subsystem_id) + unsigned int mask = 0xffff0000 | q->subdevice_mask; + unsigned int id = (q->subdevice | (q->subvendor << 16)) & mask; + if ((codec->subsystem_id & mask) == id) break; } -- cgit From 6dfeb703e386369d9f1585d29482efe7b2b4401d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 22 Nov 2011 20:00:31 +0100 Subject: ALSA: hda - Fix invalid pin and GPIO for Apple laptops with CS codecs The PCI SSID 8086:7270 is commonly used for multiple Apple machines, thus we can't use it as identifier for a unique model. Because of this conflict, some machines show weird behavior. For example, MacBook Air shows Front and Surround speakers although only Surround works due to the wrongly overridden pin-configuration for imac27. This patch fixes two things: - Stop the wrong pin-config override of imac27 by removing PCI SSID entry for avoiding the wrong mappings, - Add the generic GPIO setup for Apple machines by checking the codec SSID vendor bits Tested-by: Linus Torvalds Tested-by: Dirk Hohndel Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_cirrus.c | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 2fbab8e29576..7bd2a52f2bac 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c @@ -58,6 +58,8 @@ struct cs_spec { unsigned int gpio_mask; unsigned int gpio_dir; unsigned int gpio_data; + unsigned int gpio_eapd_hp; /* EAPD GPIO bit for headphones */ + unsigned int gpio_eapd_speaker; /* EAPD GPIO bit for speakers */ struct hda_pcm pcm_rec[2]; /* PCM information */ @@ -76,6 +78,7 @@ enum { CS420X_MBP53, CS420X_MBP55, CS420X_IMAC27, + CS420X_APPLE, CS420X_AUTO, CS420X_MODELS }; @@ -928,10 +931,9 @@ static void cs_automute(struct hda_codec *codec) spdif_present ? 0 : PIN_OUT); } } - if (spec->board_config == CS420X_MBP53 || - spec->board_config == CS420X_MBP55 || - spec->board_config == CS420X_IMAC27) { - unsigned int gpio = hp_present ? 0x02 : 0x08; + if (spec->gpio_eapd_hp) { + unsigned int gpio = hp_present ? + spec->gpio_eapd_hp : spec->gpio_eapd_speaker; snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, gpio); } @@ -1276,6 +1278,7 @@ static const char * const cs420x_models[CS420X_MODELS] = { [CS420X_MBP53] = "mbp53", [CS420X_MBP55] = "mbp55", [CS420X_IMAC27] = "imac27", + [CS420X_IMAC27] = "apple", [CS420X_AUTO] = "auto", }; @@ -1285,7 +1288,13 @@ static const struct snd_pci_quirk cs420x_cfg_tbl[] = { SND_PCI_QUIRK(0x10de, 0x0d94, "MacBookAir 3,1(2)", CS420X_MBP55), SND_PCI_QUIRK(0x10de, 0xcb79, "MacBookPro 5,5", CS420X_MBP55), SND_PCI_QUIRK(0x10de, 0xcb89, "MacBookPro 7,1", CS420X_MBP55), - SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27), + /* this conflicts with too many other models */ + /*SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27),*/ + {} /* terminator */ +}; + +static const struct snd_pci_quirk cs420x_codec_cfg_tbl[] = { + SND_PCI_QUIRK_VENDOR(0x106b, "Apple", CS420X_APPLE), {} /* terminator */ }; @@ -1367,6 +1376,10 @@ static int patch_cs420x(struct hda_codec *codec) spec->board_config = snd_hda_check_board_config(codec, CS420X_MODELS, cs420x_models, cs420x_cfg_tbl); + if (spec->board_config < 0) + spec->board_config = + snd_hda_check_board_codec_sid_config(codec, + CS420X_MODELS, NULL, cs420x_codec_cfg_tbl); if (spec->board_config >= 0) fix_pincfg(codec, spec->board_config, cs_pincfgs); @@ -1374,10 +1387,11 @@ static int patch_cs420x(struct hda_codec *codec) case CS420X_IMAC27: case CS420X_MBP53: case CS420X_MBP55: - /* GPIO1 = headphones */ - /* GPIO3 = speakers */ - spec->gpio_mask = 0x0a; - spec->gpio_dir = 0x0a; + case CS420X_APPLE: + spec->gpio_eapd_hp = 2; /* GPIO1 = headphones */ + spec->gpio_eapd_speaker = 8; /* GPIO3 = speakers */ + spec->gpio_mask = spec->gpio_dir = + spec->gpio_eapd_hp | spec->gpio_eapd_speaker; break; } -- cgit From 6759dc323826c2c806c998cd93945c5476688dd2 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 23 Nov 2011 07:38:59 +0100 Subject: ALSA: hda/realtek - Fix missing inits of item indices for auto-mic When the imux entries are rebuilt in alc_rebuild_imux_for_auto_mic(), the initialization of index field is missing. It may work without it casually when the original imux was created by the auto-parser, but it's definitely broken in the case of static configs where no imux was parsed beforehand. Because of this, the auto-mic switching doesn't work properly on some model options. This patch adds the missing initialization of index field. Reported-by: Dmitry Nezhevenko Cc: [v3.1] Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 336d14eb72af..06c0c12d4fec 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -1054,8 +1054,20 @@ static bool alc_rebuild_imux_for_auto_mic(struct hda_codec *codec) spec->imux_pins[2] = spec->dock_mic_pin; for (i = 0; i < 3; i++) { strcpy(imux->items[i].label, texts[i]); - if (spec->imux_pins[i]) + if (spec->imux_pins[i]) { + hda_nid_t pin = spec->imux_pins[i]; + int c; + for (c = 0; c < spec->num_adc_nids; c++) { + hda_nid_t cap = spec->capsrc_nids ? + spec->capsrc_nids[c] : spec->adc_nids[c]; + int idx = get_connection_index(codec, cap, pin); + if (idx >= 0) { + imux->items[i].index = idx; + break; + } + } imux->num_items = i + 1; + } } spec->num_mux_defs = 1; spec->input_mux = imux; -- cgit From 61071594f64ed12328046f94716d1d744bddc0a1 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 23 Nov 2011 07:52:15 +0100 Subject: ALSA: hda/realtek - Minor cleanup Use an inline function for the common pattern for assigning a capsrc. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 06c0c12d4fec..cbde019d3d52 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -277,6 +277,12 @@ static bool alc_dyn_adc_pcm_resetup(struct hda_codec *codec, int cur) return false; } +static inline hda_nid_t get_capsrc(struct alc_spec *spec, int idx) +{ + return spec->capsrc_nids ? + spec->capsrc_nids[idx] : spec->adc_nids[idx]; +} + /* select the given imux item; either unmute exclusively or select the route */ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx, unsigned int idx, bool force) @@ -303,8 +309,7 @@ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx, adc_idx = spec->dyn_adc_idx[idx]; } - nid = spec->capsrc_nids ? - spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx]; + nid = get_capsrc(spec, adc_idx); /* no selection? */ num_conns = snd_hda_get_conn_list(codec, nid, NULL); @@ -1058,8 +1063,7 @@ static bool alc_rebuild_imux_for_auto_mic(struct hda_codec *codec) hda_nid_t pin = spec->imux_pins[i]; int c; for (c = 0; c < spec->num_adc_nids; c++) { - hda_nid_t cap = spec->capsrc_nids ? - spec->capsrc_nids[c] : spec->adc_nids[c]; + hda_nid_t cap = get_capsrc(spec, c); int idx = get_connection_index(codec, cap, pin); if (idx >= 0) { imux->items[i].index = idx; @@ -1969,10 +1973,8 @@ static int alc_build_controls(struct hda_codec *codec) if (!kctl) kctl = snd_hda_find_mixer_ctl(codec, "Input Source"); for (i = 0; kctl && i < kctl->count; i++) { - const hda_nid_t *nids = spec->capsrc_nids; - if (!nids) - nids = spec->adc_nids; - err = snd_hda_add_nid(codec, kctl, i, nids[i]); + err = snd_hda_add_nid(codec, kctl, i, + get_capsrc(spec, i)); if (err < 0) return err; } @@ -2759,8 +2761,7 @@ static int alc_auto_create_input_ctls(struct hda_codec *codec) } for (c = 0; c < num_adcs; c++) { - hda_nid_t cap = spec->capsrc_nids ? - spec->capsrc_nids[c] : spec->adc_nids[c]; + hda_nid_t cap = get_capsrc(spec, c); idx = get_connection_index(codec, cap, pin); if (idx >= 0) { spec->imux_pins[imux->num_items] = pin; @@ -3706,8 +3707,7 @@ static int init_capsrc_for_pin(struct hda_codec *codec, hda_nid_t pin) if (!pin) return 0; for (i = 0; i < spec->num_adc_nids; i++) { - hda_nid_t cap = spec->capsrc_nids ? - spec->capsrc_nids[i] : spec->adc_nids[i]; + hda_nid_t cap = get_capsrc(spec, i); int idx; idx = get_connection_index(codec, cap, pin); -- cgit From 4ca8af579c9748376db537575f7a811c179fe50a Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Wed, 23 Nov 2011 10:39:10 +0100 Subject: ASoC: drop support for PlayPaq with WM8510 SoC Audio support for PlayPaq with WM8510 got added in commit 9aaca9683b ("[ALSA] Revised AT32 ASoC Patch"). That support depends on BOARD_PLAYPAQ. That Kconfig symbol didn't exist when that support got added in v2.6.27. It still doesn't. It has never been possible to even build this driver. Drop it. Signed-off-by: Paul Bolle Signed-off-by: Mark Brown --- sound/soc/atmel/Kconfig | 21 +- sound/soc/atmel/Makefile | 4 - sound/soc/atmel/playpaq_wm8510.c | 473 --------------------------------------- 3 files changed, 1 insertion(+), 497 deletions(-) delete mode 100644 sound/soc/atmel/playpaq_wm8510.c diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig index bee3c94f58b0..d1fcc816ce97 100644 --- a/sound/soc/atmel/Kconfig +++ b/sound/soc/atmel/Kconfig @@ -1,6 +1,6 @@ config SND_ATMEL_SOC tristate "SoC Audio for the Atmel System-on-Chip" - depends on ARCH_AT91 || AVR32 + depends on ARCH_AT91 help Say Y or M if you want to add support for codecs attached to the ATMEL SSC interface. You will also need @@ -24,25 +24,6 @@ config SND_AT91_SOC_SAM9G20_WM8731 Say Y if you want to add support for SoC audio on WM8731-based AT91sam9g20 evaluation board. -config SND_AT32_SOC_PLAYPAQ - tristate "SoC Audio support for PlayPaq with WM8510" - depends on SND_ATMEL_SOC && BOARD_PLAYPAQ && AT91_PROGRAMMABLE_CLOCKS - select SND_ATMEL_SOC_SSC - select SND_SOC_WM8510 - help - Say Y or M here if you want to add support for SoC audio - on the LRS PlayPaq. - -config SND_AT32_SOC_PLAYPAQ_SLAVE - bool "Run CODEC on PlayPaq in slave mode" - depends on SND_AT32_SOC_PLAYPAQ - default n - help - Say Y if you want to run with the AT32 SSC generating the BCLK - and FRAME signals on the PlayPaq. Unless you want to play - with the AT32 as the SSC master, you probably want to say N here, - as this will give you better sound quality. - config SND_AT91_SOC_AFEB9260 tristate "SoC Audio support for AFEB9260 board" depends on ARCH_AT91 && MACH_AFEB9260 && SND_ATMEL_SOC diff --git a/sound/soc/atmel/Makefile b/sound/soc/atmel/Makefile index e7ea56bd5f82..a5c0bf19da78 100644 --- a/sound/soc/atmel/Makefile +++ b/sound/soc/atmel/Makefile @@ -8,9 +8,5 @@ obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel_ssc_dai.o # AT91 Machine Support snd-soc-sam9g20-wm8731-objs := sam9g20_wm8731.o -# AT32 Machine Support -snd-soc-playpaq-objs := playpaq_wm8510.o - obj-$(CONFIG_SND_AT91_SOC_SAM9G20_WM8731) += snd-soc-sam9g20-wm8731.o -obj-$(CONFIG_SND_AT32_SOC_PLAYPAQ) += snd-soc-playpaq.o obj-$(CONFIG_SND_AT91_SOC_AFEB9260) += snd-soc-afeb9260.o diff --git a/sound/soc/atmel/playpaq_wm8510.c b/sound/soc/atmel/playpaq_wm8510.c deleted file mode 100644 index 73ae99ad4578..000000000000 --- a/sound/soc/atmel/playpaq_wm8510.c +++ /dev/null @@ -1,473 +0,0 @@ -/* sound/soc/at32/playpaq_wm8510.c - * ASoC machine driver for PlayPaq using WM8510 codec - * - * Copyright (C) 2008 Long Range Systems - * Geoffrey Wossum - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This code is largely inspired by sound/soc/at91/eti_b1_wm8731.c - * - * NOTE: If you don't have the AT32 enhanced portmux configured (which - * isn't currently in the mainline or Atmel patched kernel), you will - * need to set the MCLK pin (PA30) to peripheral A in your board initialization - * code. Something like: - * at32_select_periph(GPIO_PIN_PA(30), GPIO_PERIPH_A, 0); - * - */ - -/* #define DEBUG */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include "../codecs/wm8510.h" -#include "atmel-pcm.h" -#include "atmel_ssc_dai.h" - - -/*-------------------------------------------------------------------------*\ - * constants -\*-------------------------------------------------------------------------*/ -#define MCLK_PIN GPIO_PIN_PA(30) -#define MCLK_PERIPH GPIO_PERIPH_A - - -/*-------------------------------------------------------------------------*\ - * data types -\*-------------------------------------------------------------------------*/ -/* SSC clocking data */ -struct ssc_clock_data { - /* CMR div */ - unsigned int cmr_div; - - /* Frame period (as needed by xCMR.PERIOD) */ - unsigned int period; - - /* The SSC clock rate these settings where calculated for */ - unsigned long ssc_rate; -}; - - -/*-------------------------------------------------------------------------*\ - * module data -\*-------------------------------------------------------------------------*/ -static struct clk *_gclk0; -static struct clk *_pll0; - -#define CODEC_CLK (_gclk0) - - -/*-------------------------------------------------------------------------*\ - * Sound SOC operations -\*-------------------------------------------------------------------------*/ -#if defined CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE -static struct ssc_clock_data playpaq_wm8510_calc_ssc_clock( - struct snd_pcm_hw_params *params, - struct snd_soc_dai *cpu_dai) -{ - struct at32_ssc_info *ssc_p = snd_soc_dai_get_drvdata(cpu_dai); - struct ssc_device *ssc = ssc_p->ssc; - struct ssc_clock_data cd; - unsigned int rate, width_bits, channels; - unsigned int bitrate, ssc_div; - unsigned actual_rate; - - - /* - * Figure out required bitrate - */ - rate = params_rate(params); - channels = params_channels(params); - width_bits = snd_pcm_format_physical_width(params_format(params)); - bitrate = rate * width_bits * channels; - - - /* - * Figure out required SSC divider and period for required bitrate - */ - cd.ssc_rate = clk_get_rate(ssc->clk); - ssc_div = cd.ssc_rate / bitrate; - cd.cmr_div = ssc_div / 2; - if (ssc_div & 1) { - /* round cmr_div up */ - cd.cmr_div++; - } - cd.period = width_bits - 1; - - - /* - * Find actual rate, compare to requested rate - */ - actual_rate = (cd.ssc_rate / (cd.cmr_div * 2)) / (2 * (cd.period + 1)); - pr_debug("playpaq_wm8510: Request rate = %u, actual rate = %u\n", - rate, actual_rate); - - - return cd; -} -#endif /* CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE */ - - - -static int playpaq_wm8510_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - struct at32_ssc_info *ssc_p = snd_soc_dai_get_drvdata(cpu_dai); - struct ssc_device *ssc = ssc_p->ssc; - unsigned int pll_out = 0, bclk = 0, mclk_div = 0; - int ret; - - - /* Due to difficulties with getting the correct clocks from the AT32's - * PLL0, we're going to let the CODEC be in charge of all the clocks - */ -#if !defined CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE - const unsigned int fmt = (SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM); -#else - struct ssc_clock_data cd; - const unsigned int fmt = (SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS); -#endif - - if (ssc == NULL) { - pr_warning("playpaq_wm8510_hw_params: ssc is NULL!\n"); - return -EINVAL; - } - - - /* - * Figure out PLL and BCLK dividers for WM8510 - */ - switch (params_rate(params)) { - case 48000: - pll_out = 24576000; - mclk_div = WM8510_MCLKDIV_2; - bclk = WM8510_BCLKDIV_8; - break; - - case 44100: - pll_out = 22579200; - mclk_div = WM8510_MCLKDIV_2; - bclk = WM8510_BCLKDIV_8; - break; - - case 22050: - pll_out = 22579200; - mclk_div = WM8510_MCLKDIV_4; - bclk = WM8510_BCLKDIV_8; - break; - - case 16000: - pll_out = 24576000; - mclk_div = WM8510_MCLKDIV_6; - bclk = WM8510_BCLKDIV_8; - break; - - case 11025: - pll_out = 22579200; - mclk_div = WM8510_MCLKDIV_8; - bclk = WM8510_BCLKDIV_8; - break; - - case 8000: - pll_out = 24576000; - mclk_div = WM8510_MCLKDIV_12; - bclk = WM8510_BCLKDIV_8; - break; - - default: - pr_warning("playpaq_wm8510: Unsupported sample rate %d\n", - params_rate(params)); - return -EINVAL; - } - - - /* - * set CPU and CODEC DAI configuration - */ - ret = snd_soc_dai_set_fmt(codec_dai, fmt); - if (ret < 0) { - pr_warning("playpaq_wm8510: " - "Failed to set CODEC DAI format (%d)\n", - ret); - return ret; - } - ret = snd_soc_dai_set_fmt(cpu_dai, fmt); - if (ret < 0) { - pr_warning("playpaq_wm8510: " - "Failed to set CPU DAI format (%d)\n", - ret); - return ret; - } - - - /* - * Set CPU clock configuration - */ -#if defined CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE - cd = playpaq_wm8510_calc_ssc_clock(params, cpu_dai); - pr_debug("playpaq_wm8510: cmr_div = %d, period = %d\n", - cd.cmr_div, cd.period); - ret = snd_soc_dai_set_clkdiv(cpu_dai, AT32_SSC_CMR_DIV, cd.cmr_div); - if (ret < 0) { - pr_warning("playpaq_wm8510: Failed to set CPU CMR_DIV (%d)\n", - ret); - return ret; - } - ret = snd_soc_dai_set_clkdiv(cpu_dai, AT32_SSC_TCMR_PERIOD, - cd.period); - if (ret < 0) { - pr_warning("playpaq_wm8510: " - "Failed to set CPU transmit period (%d)\n", - ret); - return ret; - } -#endif /* CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE */ - - - /* - * Set CODEC clock configuration - */ - pr_debug("playpaq_wm8510: " - "pll_in = %ld, pll_out = %u, bclk = %x, mclk = %x\n", - clk_get_rate(CODEC_CLK), pll_out, bclk, mclk_div); - - -#if !defined CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE - ret = snd_soc_dai_set_clkdiv(codec_dai, WM8510_BCLKDIV, bclk); - if (ret < 0) { - pr_warning - ("playpaq_wm8510: Failed to set CODEC DAI BCLKDIV (%d)\n", - ret); - return ret; - } -#endif /* CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE */ - - - ret = snd_soc_dai_set_pll(codec_dai, 0, 0, - clk_get_rate(CODEC_CLK), pll_out); - if (ret < 0) { - pr_warning("playpaq_wm8510: Failed to set CODEC DAI PLL (%d)\n", - ret); - return ret; - } - - - ret = snd_soc_dai_set_clkdiv(codec_dai, WM8510_MCLKDIV, mclk_div); - if (ret < 0) { - pr_warning("playpaq_wm8510: Failed to set CODEC MCLKDIV (%d)\n", - ret); - return ret; - } - - - return 0; -} - - - -static struct snd_soc_ops playpaq_wm8510_ops = { - .hw_params = playpaq_wm8510_hw_params, -}; - - - -static const struct snd_soc_dapm_widget playpaq_dapm_widgets[] = { - SND_SOC_DAPM_MIC("Int Mic", NULL), - SND_SOC_DAPM_SPK("Ext Spk", NULL), -}; - - - -static const struct snd_soc_dapm_route intercon[] = { - /* speaker connected to SPKOUT */ - {"Ext Spk", NULL, "SPKOUTP"}, - {"Ext Spk", NULL, "SPKOUTN"}, - - {"Mic Bias", NULL, "Int Mic"}, - {"MICN", NULL, "Mic Bias"}, - {"MICP", NULL, "Mic Bias"}, -}; - - - -static int playpaq_wm8510_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - int i; - - /* - * Add DAPM widgets - */ - for (i = 0; i < ARRAY_SIZE(playpaq_dapm_widgets); i++) - snd_soc_dapm_new_control(dapm, &playpaq_dapm_widgets[i]); - - - - /* - * Setup audio path interconnects - */ - snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon)); - - - - /* always connected pins */ - snd_soc_dapm_enable_pin(dapm, "Int Mic"); - snd_soc_dapm_enable_pin(dapm, "Ext Spk"); - - - - /* Make CSB show PLL rate */ - snd_soc_dai_set_clkdiv(rtd->codec_dai, WM8510_OPCLKDIV, - WM8510_OPCLKDIV_1 | 4); - - return 0; -} - - - -static struct snd_soc_dai_link playpaq_wm8510_dai = { - .name = "WM8510", - .stream_name = "WM8510 PCM", - .cpu_dai_name= "atmel-ssc-dai.0", - .platform_name = "atmel-pcm-audio", - .codec_name = "wm8510-codec.0-0x1a", - .codec_dai_name = "wm8510-hifi", - .init = playpaq_wm8510_init, - .ops = &playpaq_wm8510_ops, -}; - - - -static struct snd_soc_card snd_soc_playpaq = { - .name = "LRS_PlayPaq_WM8510", - .dai_link = &playpaq_wm8510_dai, - .num_links = 1, -}; - -static struct platform_device *playpaq_snd_device; - - -static int __init playpaq_asoc_init(void) -{ - int ret = 0; - - /* - * Configure MCLK for WM8510 - */ - _gclk0 = clk_get(NULL, "gclk0"); - if (IS_ERR(_gclk0)) { - _gclk0 = NULL; - ret = PTR_ERR(_gclk0); - goto err_gclk0; - } - _pll0 = clk_get(NULL, "pll0"); - if (IS_ERR(_pll0)) { - _pll0 = NULL; - ret = PTR_ERR(_pll0); - goto err_pll0; - } - ret = clk_set_parent(_gclk0, _pll0); - if (ret) { - pr_warning("snd-soc-playpaq: " - "Failed to set PLL0 as parent for DAC clock\n"); - goto err_set_clk; - } - clk_set_rate(CODEC_CLK, 12000000); - clk_enable(CODEC_CLK); - -#if defined CONFIG_AT32_ENHANCED_PORTMUX - at32_select_periph(MCLK_PIN, MCLK_PERIPH, 0); -#endif - - - /* - * Create and register platform device - */ - playpaq_snd_device = platform_device_alloc("soc-audio", 0); - if (playpaq_snd_device == NULL) { - ret = -ENOMEM; - goto err_device_alloc; - } - - platform_set_drvdata(playpaq_snd_device, &snd_soc_playpaq); - - ret = platform_device_add(playpaq_snd_device); - if (ret) { - pr_warning("playpaq_wm8510: platform_device_add failed (%d)\n", - ret); - goto err_device_add; - } - - return 0; - - -err_device_add: - if (playpaq_snd_device != NULL) { - platform_device_put(playpaq_snd_device); - playpaq_snd_device = NULL; - } -err_device_alloc: -err_set_clk: - if (_pll0 != NULL) { - clk_put(_pll0); - _pll0 = NULL; - } -err_pll0: - if (_gclk0 != NULL) { - clk_put(_gclk0); - _gclk0 = NULL; - } - return ret; -} - - -static void __exit playpaq_asoc_exit(void) -{ - if (_gclk0 != NULL) { - clk_put(_gclk0); - _gclk0 = NULL; - } - if (_pll0 != NULL) { - clk_put(_pll0); - _pll0 = NULL; - } - -#if defined CONFIG_AT32_ENHANCED_PORTMUX - at32_free_pin(MCLK_PIN); -#endif - - platform_device_unregister(playpaq_snd_device); - playpaq_snd_device = NULL; -} - -module_init(playpaq_asoc_init); -module_exit(playpaq_asoc_exit); - -MODULE_AUTHOR("Geoffrey Wossum "); -MODULE_DESCRIPTION("ASoC machine driver for LRS PlayPaq"); -MODULE_LICENSE("GPL"); -- cgit From b284362b6b45150d171ff5bed92bc416b040aead Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 23 Nov 2011 12:46:11 +0800 Subject: ASoC: cs42l51: Fix off-by-one for reg_cache_size Just checking the code in cs42l51_fill_cache(): The cache pointer points to codec->reg_cache + 1. I think it is because CS42L51_FIRSTREG is 0x01, so codec->reg_cache[0] is not used here. Then we read CS42L51_NUMREGS bytes to cache. So we need reg_cache_size to be CS42L51_NUMREGS + 1. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l51.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index 8c3c8205d19e..1ee66361f61b 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c @@ -555,7 +555,7 @@ static int cs42l51_probe(struct snd_soc_codec *codec) static struct snd_soc_codec_driver soc_codec_device_cs42l51 = { .probe = cs42l51_probe, - .reg_cache_size = CS42L51_NUMREGS, + .reg_cache_size = CS42L51_NUMREGS + 1, .reg_word_size = sizeof(u8), }; -- cgit From 5ff1ddf22b2584d00d7e0ba5a8eab07b5338bd84 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Wed, 23 Nov 2011 22:37:00 +0800 Subject: ASoC: skip resume of soc-audio devices without codecs There are cases where there is no working codec on the soc-audio devices, and snd_soc_suspend() will skip such device when suspending. Yet its counterpart snd_soc_resume() does not check this, causing complaints about spinlock lockup: [ 176.726087] BUG: spinlock lockup on CPU#0, kworker/0:2/1067, d8ab82a8 [ 176.732539] [<80014a14>] (unwind_backtrace+0x0/0xec) from [<805b3fc8>] (dump_stack+0x20/0x24) [ 176.741082] [<805b3fc8>] (dump_stack+0x20/0x24) from [<80322208>] (do_raw_spin_lock+0x118/0x158) [ 176.749882] [<80322208>] (do_raw_spin_lock+0x118/0x158) from [<805b7874>] (_raw_spin_lock_irqsave+0x5c/0x68) [ 176.759723] [<805b7874>] (_raw_spin_lock_irqsave+0x5c/0x68) from [<8002a020>] (__wake_up+0x2c/0x5c) [ 176.768781] [<8002a020>] (__wake_up+0x2c/0x5c) from [<804a6de8>] (soc_resume_deferred+0x3c/0x2b0) [ 176.777666] [<804a6de8>] (soc_resume_deferred+0x3c/0x2b0) from [<8004ee20>] (process_one_work+0x2e8/0x50c) [ 176.787334] [<8004ee20>] (process_one_work+0x2e8/0x50c) from [<8004fd08>] (worker_thread+0x1c8/0x2e0) [ 176.796566] [<8004fd08>] (worker_thread+0x1c8/0x2e0) from [<80053ec8>] (kthread+0xa4/0xb0) [ 176.804843] [<80053ec8>] (kthread+0xa4/0xb0) from [<8000ea70>] (kernel_thread_exit+0x0/0x8) Signed-off-by: Eric Miao Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index a5d3685a5d38..a25fa63ce9a2 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -709,6 +709,12 @@ int snd_soc_resume(struct device *dev) struct snd_soc_card *card = dev_get_drvdata(dev); int i, ac97_control = 0; + /* If the initialization of this soc device failed, there is no codec + * associated with it. Just bail out in this case. + */ + if (list_empty(&card->codec_dev_list)) + return 0; + /* AC97 devices might have other drivers hanging off them so * need to resume immediately. Other drivers don't have that * problem and may take a substantial amount of time to resume -- cgit From 5b895eec118ab5fec7b69102d73c1b04a86140b9 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 27 Nov 2011 15:54:49 +0000 Subject: ASoC: Correct name of Speyside Main Speaker widget Signed-off-by: Mark Brown --- sound/soc/samsung/speyside.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/samsung/speyside.c b/sound/soc/samsung/speyside.c index 85bf541a771d..4b8e35410eb1 100644 --- a/sound/soc/samsung/speyside.c +++ b/sound/soc/samsung/speyside.c @@ -191,7 +191,7 @@ static int speyside_late_probe(struct snd_soc_card *card) snd_soc_dapm_ignore_suspend(&card->dapm, "Headset Mic"); snd_soc_dapm_ignore_suspend(&card->dapm, "Main AMIC"); snd_soc_dapm_ignore_suspend(&card->dapm, "Main DMIC"); - snd_soc_dapm_ignore_suspend(&card->dapm, "Speaker"); + snd_soc_dapm_ignore_suspend(&card->dapm, "Main Speaker"); snd_soc_dapm_ignore_suspend(&card->dapm, "WM1250 Output"); snd_soc_dapm_ignore_suspend(&card->dapm, "WM1250 Input"); -- cgit From 92bb43e6aae3dbdb199feba93da5f2d05d7716d0 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 24 Nov 2011 14:48:24 +0300 Subject: ALSA: hda - cut and paste typo in cs420x_models[] The CS420X_IMAC27 was copied from the line before but CS420X_APPLE was clearly intented. Signed-off-by: Dan Carpenter Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_cirrus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 7bd2a52f2bac..70a7abda7e22 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c @@ -1278,7 +1278,7 @@ static const char * const cs420x_models[CS420X_MODELS] = { [CS420X_MBP53] = "mbp53", [CS420X_MBP55] = "mbp55", [CS420X_IMAC27] = "imac27", - [CS420X_IMAC27] = "apple", + [CS420X_APPLE] = "apple", [CS420X_AUTO] = "auto", }; -- cgit From 187d333edc0a8e1bb507900ce89853ffe3bd2c84 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 24 Nov 2011 16:33:09 +0100 Subject: ALSA: hda - Fix jack-detection control of VT1708 VT1708 has no support for unsolicited events per jack-plug, the driver implements the workq for polling the jack-detection. The mixer element "Jack Detect" was supposed to control this behavior on/off, but this doesn't work properly as is now. The workq is always started and the HP automute is always enabled. This patch fixes the jack-detect control behavior by triggering / stopping the work appropriately at the state change. Also the work checks the internal state to continue scheduling or not. Cc: [v3.1] Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_via.c | 76 +++++++++++++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 33 deletions(-) diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 431c0d417eeb..b5137629f8e9 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -208,6 +208,7 @@ struct via_spec { /* work to check hp jack state */ struct hda_codec *codec; struct delayed_work vt1708_hp_work; + int hp_work_active; int vt1708_jack_detect; int vt1708_hp_present; @@ -305,27 +306,35 @@ enum { static void analog_low_current_mode(struct hda_codec *codec); static bool is_aa_path_mute(struct hda_codec *codec); -static void vt1708_start_hp_work(struct via_spec *spec) +#define hp_detect_with_aa(codec) \ + (snd_hda_get_bool_hint(codec, "analog_loopback_hp_detect") == 1 && \ + !is_aa_path_mute(codec)) + +static void vt1708_stop_hp_work(struct via_spec *spec) { if (spec->codec_type != VT1708 || spec->autocfg.hp_pins[0] == 0) return; - snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81, - !spec->vt1708_jack_detect); - if (!delayed_work_pending(&spec->vt1708_hp_work)) - schedule_delayed_work(&spec->vt1708_hp_work, - msecs_to_jiffies(100)); + if (spec->hp_work_active) { + snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81, 1); + cancel_delayed_work_sync(&spec->vt1708_hp_work); + spec->hp_work_active = 0; + } } -static void vt1708_stop_hp_work(struct via_spec *spec) +static void vt1708_update_hp_work(struct via_spec *spec) { if (spec->codec_type != VT1708 || spec->autocfg.hp_pins[0] == 0) return; - if (snd_hda_get_bool_hint(spec->codec, "analog_loopback_hp_detect") == 1 - && !is_aa_path_mute(spec->codec)) - return; - snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81, - !spec->vt1708_jack_detect); - cancel_delayed_work_sync(&spec->vt1708_hp_work); + if (spec->vt1708_jack_detect && + (spec->active_streams || hp_detect_with_aa(spec->codec))) { + if (!spec->hp_work_active) { + snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81, 0); + schedule_delayed_work(&spec->vt1708_hp_work, + msecs_to_jiffies(100)); + spec->hp_work_active = 1; + } + } else if (!hp_detect_with_aa(spec->codec)) + vt1708_stop_hp_work(spec); } static void set_widgets_power_state(struct hda_codec *codec) @@ -343,12 +352,7 @@ static int analog_input_switch_put(struct snd_kcontrol *kcontrol, set_widgets_power_state(codec); analog_low_current_mode(snd_kcontrol_chip(kcontrol)); - if (snd_hda_get_bool_hint(codec, "analog_loopback_hp_detect") == 1) { - if (is_aa_path_mute(codec)) - vt1708_start_hp_work(codec->spec); - else - vt1708_stop_hp_work(codec->spec); - } + vt1708_update_hp_work(codec->spec); return change; } @@ -1154,7 +1158,7 @@ static int via_playback_multi_pcm_prepare(struct hda_pcm_stream *hinfo, spec->cur_dac_stream_tag = stream_tag; spec->cur_dac_format = format; mutex_unlock(&spec->config_mutex); - vt1708_start_hp_work(spec); + vt1708_update_hp_work(spec); return 0; } @@ -1174,7 +1178,7 @@ static int via_playback_hp_pcm_prepare(struct hda_pcm_stream *hinfo, spec->cur_hp_stream_tag = stream_tag; spec->cur_hp_format = format; mutex_unlock(&spec->config_mutex); - vt1708_start_hp_work(spec); + vt1708_update_hp_work(spec); return 0; } @@ -1188,7 +1192,7 @@ static int via_playback_multi_pcm_cleanup(struct hda_pcm_stream *hinfo, snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); spec->active_streams &= ~STREAM_MULTI_OUT; mutex_unlock(&spec->config_mutex); - vt1708_stop_hp_work(spec); + vt1708_update_hp_work(spec); return 0; } @@ -1203,7 +1207,7 @@ static int via_playback_hp_pcm_cleanup(struct hda_pcm_stream *hinfo, snd_hda_codec_setup_stream(codec, spec->hp_dac_nid, 0, 0, 0); spec->active_streams &= ~STREAM_INDEP_HP; mutex_unlock(&spec->config_mutex); - vt1708_stop_hp_work(spec); + vt1708_update_hp_work(spec); return 0; } @@ -1645,7 +1649,8 @@ static void via_hp_automute(struct hda_codec *codec) int nums; struct via_spec *spec = codec->spec; - if (!spec->hp_independent_mode && spec->autocfg.hp_pins[0]) + if (!spec->hp_independent_mode && spec->autocfg.hp_pins[0] && + (spec->codec_type != VT1708 || spec->vt1708_jack_detect)) present = snd_hda_jack_detect(codec, spec->autocfg.hp_pins[0]); if (spec->smart51_enabled) @@ -2612,8 +2617,6 @@ static int vt1708_jack_detect_get(struct snd_kcontrol *kcontrol, if (spec->codec_type != VT1708) return 0; - spec->vt1708_jack_detect = - !((snd_hda_codec_read(codec, 0x1, 0, 0xf84, 0) >> 8) & 0x1); ucontrol->value.integer.value[0] = spec->vt1708_jack_detect; return 0; } @@ -2623,18 +2626,22 @@ static int vt1708_jack_detect_put(struct snd_kcontrol *kcontrol, { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct via_spec *spec = codec->spec; - int change; + int val; if (spec->codec_type != VT1708) return 0; - spec->vt1708_jack_detect = ucontrol->value.integer.value[0]; - change = (0x1 & (snd_hda_codec_read(codec, 0x1, 0, 0xf84, 0) >> 8)) - == !spec->vt1708_jack_detect; - if (spec->vt1708_jack_detect) { + val = !!ucontrol->value.integer.value[0]; + if (spec->vt1708_jack_detect == val) + return 0; + spec->vt1708_jack_detect = val; + if (spec->vt1708_jack_detect && + snd_hda_get_bool_hint(codec, "analog_loopback_hp_detect") != 1) { mute_aa_path(codec, 1); notify_aa_path_ctls(codec); } - return change; + via_hp_automute(codec); + vt1708_update_hp_work(spec); + return 1; } static const struct snd_kcontrol_new vt1708_jack_detect_ctl = { @@ -2771,6 +2778,7 @@ static int via_init(struct hda_codec *codec) via_auto_init_unsol_event(codec); via_hp_automute(codec); + vt1708_update_hp_work(spec); return 0; } @@ -2787,7 +2795,9 @@ static void vt1708_update_hp_jack_state(struct work_struct *work) spec->vt1708_hp_present ^= 1; via_hp_automute(spec->codec); } - vt1708_start_hp_work(spec); + if (spec->vt1708_jack_detect) + schedule_delayed_work(&spec->vt1708_hp_work, + msecs_to_jiffies(100)); } static int get_mux_nids(struct hda_codec *codec) -- cgit From fc07ecd851bd082265b52838eff12f50b88f6114 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 28 Nov 2011 21:16:56 +0000 Subject: ASoC: Error out if we can't generate a LRCLK at all for WM8994 Signed-off-by: Mark Brown --- sound/soc/codecs/wm8994.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 9c982e47eb99..36ba1edfff80 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -2357,6 +2357,11 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream, bclk |= best << WM8994_AIF1_BCLK_DIV_SHIFT; lrclk = bclk_rate / params_rate(params); + if (!lrclk) { + dev_err(dai->dev, "Unable to generate LRCLK from %dHz BCLK\n", + bclk_rate); + return -EINVAL; + } dev_dbg(dai->dev, "Using LRCLK rate %d for actual LRCLK %dHz\n", lrclk, bclk_rate / lrclk); -- cgit From fc8e6e8668e74fbf8e00d6e143d7f43b20f73f32 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 28 Nov 2011 18:48:46 +0000 Subject: ASoC: Supply dcs_codes for newer WM1811 revisions Based on initial data. Signed-off-by: Mark Brown --- sound/soc/codecs/wm8994.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 36ba1edfff80..6c2988549003 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -3183,6 +3183,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) switch (wm8994->revision) { case 0: case 1: + case 2: + case 3: wm8994->hubs.dcs_codes_l = -9; wm8994->hubs.dcs_codes_r = -5; break; -- cgit From ae7cc709f2ec11b49fc31b20cd8c943794ae9576 Mon Sep 17 00:00:00 2001 From: John F Leach Date: Mon, 28 Nov 2011 19:41:27 -0500 Subject: ALSA: usb-audio - Support for Roland GAIA SH-01 Synthesizer Added table quirks entry for Roland GAIA SH-01 Synthesizer based upon Roland SH-201 table entry as template. USB MIDI and audio was tested with Muse and Audacity. Signed-off-by: John F Leach Signed-off-by: Takashi Iwai --- sound/usb/quirks-table.h | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index b61945f3af9e..32d2a21f2e3b 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -1632,6 +1632,37 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, +{ + /* Roland GAIA SH-01 */ + USB_DEVICE(0x0582, 0x0111), + .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + .vendor_name = "Roland", + .product_name = "GAIA", + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_COMPOSITE, + .data = (const struct snd_usb_audio_quirk[]) { + { + .ifnum = 0, + .type = QUIRK_AUDIO_STANDARD_INTERFACE + }, + { + .ifnum = 1, + .type = QUIRK_AUDIO_STANDARD_INTERFACE + }, + { + .ifnum = 2, + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = &(const struct snd_usb_midi_endpoint_info) { + .out_cables = 0x0003, + .in_cables = 0x0003 + } + }, + { + .ifnum = -1 + } + } + } +}, { USB_DEVICE(0x0582, 0x0113), .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { -- cgit From 4f718a29fe4908c2cea782f751e9805319684e2b Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 28 Nov 2011 09:44:14 +0100 Subject: firmware: Sigma: Prevent out of bounds memory access The SigmaDSP firmware loader currently does not perform enough boundary size checks when processing the firmware. As a result it is possible that a malformed firmware can cause an out of bounds memory access. This patch adds checks which ensure that both the action header and the payload are completely inside the firmware data boundaries before processing them. Signed-off-by: Lars-Peter Clausen Acked-by: Mike Frysinger Signed-off-by: Mark Brown Cc: stable@kernel.org --- drivers/firmware/sigma.c | 76 +++++++++++++++++++++++++++++++++++------------- include/linux/sigma.h | 5 ---- 2 files changed, 55 insertions(+), 26 deletions(-) diff --git a/drivers/firmware/sigma.c b/drivers/firmware/sigma.c index f10fc521951b..c780baa59ed9 100644 --- a/drivers/firmware/sigma.c +++ b/drivers/firmware/sigma.c @@ -14,13 +14,34 @@ #include #include -/* Return: 0==OK, <0==error, =1 ==no more actions */ +static size_t sigma_action_size(struct sigma_action *sa) +{ + size_t payload = 0; + + switch (sa->instr) { + case SIGMA_ACTION_WRITEXBYTES: + case SIGMA_ACTION_WRITESINGLE: + case SIGMA_ACTION_WRITESAFELOAD: + payload = sigma_action_len(sa); + break; + default: + break; + } + + payload = ALIGN(payload, 2); + + return payload + sizeof(struct sigma_action); +} + +/* + * Returns a negative error value in case of an error, 0 if processing of + * the firmware should be stopped after this action, 1 otherwise. + */ static int -process_sigma_action(struct i2c_client *client, struct sigma_firmware *ssfw) +process_sigma_action(struct i2c_client *client, struct sigma_action *sa) { - struct sigma_action *sa = (void *)(ssfw->fw->data + ssfw->pos); size_t len = sigma_action_len(sa); - int ret = 0; + int ret; pr_debug("%s: instr:%i addr:%#x len:%zu\n", __func__, sa->instr, sa->addr, len); @@ -29,44 +50,50 @@ process_sigma_action(struct i2c_client *client, struct sigma_firmware *ssfw) case SIGMA_ACTION_WRITEXBYTES: case SIGMA_ACTION_WRITESINGLE: case SIGMA_ACTION_WRITESAFELOAD: - if (ssfw->fw->size < ssfw->pos + len) - return -EINVAL; ret = i2c_master_send(client, (void *)&sa->addr, len); if (ret < 0) return -EINVAL; break; - case SIGMA_ACTION_DELAY: - ret = 0; udelay(len); len = 0; break; - case SIGMA_ACTION_END: - return 1; - + return 0; default: return -EINVAL; } - /* when arrive here ret=0 or sent data */ - ssfw->pos += sigma_action_size(sa, len); - return ssfw->pos == ssfw->fw->size; + return 1; } static int process_sigma_actions(struct i2c_client *client, struct sigma_firmware *ssfw) { - pr_debug("%s: processing %p\n", __func__, ssfw); + struct sigma_action *sa; + size_t size; + int ret; + + while (ssfw->pos + sizeof(*sa) <= ssfw->fw->size) { + sa = (struct sigma_action *)(ssfw->fw->data + ssfw->pos); + + size = sigma_action_size(sa); + ssfw->pos += size; + if (ssfw->pos > ssfw->fw->size || size == 0) + break; + + ret = process_sigma_action(client, sa); - while (1) { - int ret = process_sigma_action(client, ssfw); pr_debug("%s: action returned %i\n", __func__, ret); - if (ret == 1) - return 0; - else if (ret) + + if (ret <= 0) return ret; } + + if (ssfw->pos != ssfw->fw->size) + return -EINVAL; + + return 0; } int process_sigma_firmware(struct i2c_client *client, const char *name) @@ -89,7 +116,14 @@ int process_sigma_firmware(struct i2c_client *client, const char *name) /* then verify the header */ ret = -EINVAL; - if (fw->size < sizeof(*ssfw_head)) + + /* + * Reject too small or unreasonable large files. The upper limit has been + * chosen a bit arbitrarily, but it should be enough for all practical + * purposes and having the limit makes it easier to avoid integer + * overflows later in the loading process. + */ + if (fw->size < sizeof(*ssfw_head) || fw->size >= 0x4000000) goto done; ssfw_head = (void *)fw->data; diff --git a/include/linux/sigma.h b/include/linux/sigma.h index e2accb3164d8..9a138c2946bb 100644 --- a/include/linux/sigma.h +++ b/include/linux/sigma.h @@ -50,11 +50,6 @@ static inline u32 sigma_action_len(struct sigma_action *sa) return (sa->len_hi << 16) | sa->len; } -static inline size_t sigma_action_size(struct sigma_action *sa, u32 payload_len) -{ - return sizeof(*sa) + payload_len + (payload_len % 2); -} - extern int process_sigma_firmware(struct i2c_client *client, const char *name); #endif -- cgit From c56935bdc0a8edf50237d3b0205133a5b0adc604 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 28 Nov 2011 09:44:15 +0100 Subject: firmware: Sigma: Skip header during CRC generation The firmware header is not part of the CRC, so skip it. Otherwise the firmware will be rejected due to non-matching CRCs. Signed-off-by: Lars-Peter Clausen Acked-by: Mike Frysinger Signed-off-by: Mark Brown Cc: stable@kernel.org --- drivers/firmware/sigma.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/sigma.c b/drivers/firmware/sigma.c index c780baa59ed9..36265de0a9e8 100644 --- a/drivers/firmware/sigma.c +++ b/drivers/firmware/sigma.c @@ -130,7 +130,8 @@ int process_sigma_firmware(struct i2c_client *client, const char *name) if (memcmp(ssfw_head->magic, SIGMA_MAGIC, ARRAY_SIZE(ssfw_head->magic))) goto done; - crc = crc32(0, fw->data, fw->size); + crc = crc32(0, fw->data + sizeof(*ssfw_head), + fw->size - sizeof(*ssfw_head)); pr_debug("%s: crc=%x\n", __func__, crc); if (crc != ssfw_head->crc) goto done; -- cgit From bda63586bc5929e97288cdb371bb6456504867ed Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 28 Nov 2011 09:44:16 +0100 Subject: firmware: Sigma: Fix endianess issues Currently the SigmaDSP firmware loader only works correctly on little-endian systems. Fix this by using the proper endianess conversion functions. Signed-off-by: Lars-Peter Clausen Acked-by: Mike Frysinger Signed-off-by: Mark Brown Cc: stable@kernel.org --- drivers/firmware/sigma.c | 2 +- include/linux/sigma.h | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/firmware/sigma.c b/drivers/firmware/sigma.c index 36265de0a9e8..1eedb6f7fdab 100644 --- a/drivers/firmware/sigma.c +++ b/drivers/firmware/sigma.c @@ -133,7 +133,7 @@ int process_sigma_firmware(struct i2c_client *client, const char *name) crc = crc32(0, fw->data + sizeof(*ssfw_head), fw->size - sizeof(*ssfw_head)); pr_debug("%s: crc=%x\n", __func__, crc); - if (crc != ssfw_head->crc) + if (crc != le32_to_cpu(ssfw_head->crc)) goto done; ssfw.pos = sizeof(*ssfw_head); diff --git a/include/linux/sigma.h b/include/linux/sigma.h index 9a138c2946bb..d0de882c0d96 100644 --- a/include/linux/sigma.h +++ b/include/linux/sigma.h @@ -24,7 +24,7 @@ struct sigma_firmware { struct sigma_firmware_header { unsigned char magic[7]; u8 version; - u32 crc; + __le32 crc; }; enum { @@ -40,14 +40,14 @@ enum { struct sigma_action { u8 instr; u8 len_hi; - u16 len; - u16 addr; + __le16 len; + __be16 addr; unsigned char payload[]; }; static inline u32 sigma_action_len(struct sigma_action *sa) { - return (sa->len_hi << 16) | sa->len; + return (sa->len_hi << 16) | le16_to_cpu(sa->len); } extern int process_sigma_firmware(struct i2c_client *client, const char *name); -- cgit From 542c9a0a2fa351149c4a3467589a54cafcf0a1dd Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 29 Nov 2011 13:01:30 +0100 Subject: ALSA: hda - Avoid touching mute-VREF pin for IDT codecs Some HP laptops use a pin VREF for controlling the mute LED, and such a pin shouldn't be powered off. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index f3658658548e..f4f4ebeed9ea 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -4441,7 +4441,9 @@ static int stac92xx_init(struct hda_codec *codec) int pinctl, def_conf; /* power on when no jack detection is available */ - if (!spec->hp_detect) { + /* or when the VREF is used for controlling LED */ + if (!spec->hp_detect || + (spec->gpio_led > 8 && spec->gpio_led == nid)) { stac_toggle_power_map(codec, nid, 1); continue; } -- cgit From 4f8b6c7dc80ac9619db033c7f6fc355eab9514f5 Mon Sep 17 00:00:00 2001 From: Marc Vertes Date: Tue, 29 Nov 2011 12:21:17 +0100 Subject: ALSA: hda_intel - revert a quirk that affect VIA chipsets This quirk sould be reverted. It has the following probems: 1) The quirk was intended to "ASUS MV2-MX SE" motherboards only, but the ID used matches a much broader range, potentially all boards containing a VIA chipset model in the family of vendor VIA 0x1106 and audio device ID 0x3288, which encompasses VIA-VT82xx, VIA-VT1xx and VIA-VT20xx chipsets. 2) VIA chipsets rely on azx_via_get_position() to handle correctly dma transfers during capture. Using POS_FIX_LPIB instead of POS_FIX_VIACOMBO leads to partially corrupted input buffers during capture. The effects of this bug are not immediately visible, it took strong DSP expertise, some expensive signal generator and a spectrum analyzer to identify it and verify correct behaviour using original default. 3) It's almost certain that the quirk did not fix the real problem, if there was one. Refer to original submission: http://mailman.alsa-project.org/pipermail/alsa-devel/2010-February/025109.html Signed-of-by: Marc Vertes Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 096507d2ca9a..7d98240def0b 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2508,7 +2508,6 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = { SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB), SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS M2V", POS_FIX_LPIB), SND_PCI_QUIRK(0x104d, 0x9069, "Sony VPCS11V9E", POS_FIX_LPIB), - SND_PCI_QUIRK(0x1106, 0x3288, "ASUS M2V-MX SE", POS_FIX_LPIB), SND_PCI_QUIRK(0x1297, 0x3166, "Shuttle", POS_FIX_LPIB), SND_PCI_QUIRK(0x1458, 0xa022, "ga-ma770-ud3", POS_FIX_LPIB), SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB), -- cgit From 88d686027bb43f585914c77dd363f6e817b42c2a Mon Sep 17 00:00:00 2001 From: Charles Chin Date: Thu, 1 Dec 2011 11:21:00 +0100 Subject: ALSA: hda - Fix S3/S4 problem on machines with VREF-pin mute-LED The verb command in stac92xx_post_suspend caused the audio to stop working after resuming from S3 mode on HP laptops with the VREF-pin mute-LED control. Removing relevant post_suspend registering. Although removing D3 on AFG is no optimal solution, the impact should be small in comparison with the broken S3/S4. Signed-off-by: Charles Chin Cc: Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index f4f4ebeed9ea..d8d2f9dccd9b 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -5057,20 +5057,6 @@ static int stac92xx_pre_resume(struct hda_codec *codec) return 0; } -static int stac92xx_post_suspend(struct hda_codec *codec) -{ - struct sigmatel_spec *spec = codec->spec; - if (spec->gpio_led > 8) { - /* with vref-out pin used for mute led control - * codec AFG is prevented from D3 state, but on - * system suspend it can (and should) be used - */ - snd_hda_codec_read(codec, codec->afg, 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D3); - } - return 0; -} - static void stac92xx_set_power_state(struct hda_codec *codec, hda_nid_t fg, unsigned int power_state) { @@ -5670,8 +5656,6 @@ again: } else { codec->patch_ops.set_power_state = stac92xx_set_power_state; - codec->patch_ops.post_suspend = - stac92xx_post_suspend; } codec->patch_ops.pre_resume = stac92xx_pre_resume; codec->patch_ops.check_power_status = @@ -5985,8 +5969,6 @@ again: } else { codec->patch_ops.set_power_state = stac92xx_set_power_state; - codec->patch_ops.post_suspend = - stac92xx_post_suspend; } codec->patch_ops.pre_resume = stac92xx_pre_resume; codec->patch_ops.check_power_status = -- cgit From fc084e0b930d546872ab23667052499f7daf0fed Mon Sep 17 00:00:00 2001 From: David Dillow Date: Thu, 1 Dec 2011 23:26:53 -0500 Subject: ALSA: sis7019 - give slow codecs more time to reset There are some AC97 codec and board combinations that have been observed to take a very long time to respond after the cold reset has completed. In one case, more than 350 ms was required. To allow users to have sound on those platforms, we'll wait up to 500ms for the codec to become ready. As a board may have multiple codecs, with some faster than others to reset, we add a module parameter to inform the driver which codecs should be present. Reported-by: KotCzarny Signed-off-by: David Dillow Cc: Signed-off-by: Takashi Iwai --- sound/pci/sis7019.c | 64 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 53 insertions(+), 11 deletions(-) diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c index a391e622a192..28dfafb56dd1 100644 --- a/sound/pci/sis7019.c +++ b/sound/pci/sis7019.c @@ -41,6 +41,7 @@ MODULE_SUPPORTED_DEVICE("{{SiS,SiS7019 Audio Accelerator}}"); static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ static int enable = 1; +static int codecs = 1; module_param(index, int, 0444); MODULE_PARM_DESC(index, "Index value for SiS7019 Audio Accelerator."); @@ -48,6 +49,8 @@ module_param(id, charp, 0444); MODULE_PARM_DESC(id, "ID string for SiS7019 Audio Accelerator."); module_param(enable, bool, 0444); MODULE_PARM_DESC(enable, "Enable SiS7019 Audio Accelerator."); +module_param(codecs, int, 0444); +MODULE_PARM_DESC(codecs, "Set bit to indicate that codec number is expected to be present (default 1)"); static DEFINE_PCI_DEVICE_TABLE(snd_sis7019_ids) = { { PCI_DEVICE(PCI_VENDOR_ID_SI, 0x7019) }, @@ -140,6 +143,9 @@ struct sis7019 { dma_addr_t silence_dma_addr; }; +/* These values are also used by the module param 'codecs' to indicate + * which codecs should be present. + */ #define SIS_PRIMARY_CODEC_PRESENT 0x0001 #define SIS_SECONDARY_CODEC_PRESENT 0x0002 #define SIS_TERTIARY_CODEC_PRESENT 0x0004 @@ -1078,6 +1084,7 @@ static int sis_chip_init(struct sis7019 *sis) { unsigned long io = sis->ioport; void __iomem *ioaddr = sis->ioaddr; + unsigned long timeout; u16 status; int count; int i; @@ -1104,21 +1111,45 @@ static int sis_chip_init(struct sis7019 *sis) while ((inw(io + SIS_AC97_STATUS) & SIS_AC97_STATUS_BUSY) && --count) udelay(1); + /* Command complete, we can let go of the semaphore now. + */ + outl(SIS_AC97_SEMA_RELEASE, io + SIS_AC97_SEMA); + if (!count) + return -EIO; + /* Now that we've finished the reset, find out what's attached. + * There are some codec/board combinations that take an extremely + * long time to come up. 350+ ms has been observed in the field, + * so we'll give them up to 500ms. */ - status = inl(io + SIS_AC97_STATUS); - if (status & SIS_AC97_STATUS_CODEC_READY) - sis->codecs_present |= SIS_PRIMARY_CODEC_PRESENT; - if (status & SIS_AC97_STATUS_CODEC2_READY) - sis->codecs_present |= SIS_SECONDARY_CODEC_PRESENT; - if (status & SIS_AC97_STATUS_CODEC3_READY) - sis->codecs_present |= SIS_TERTIARY_CODEC_PRESENT; - - /* All done, let go of the semaphore, and check for errors + sis->codecs_present = 0; + timeout = msecs_to_jiffies(500) + jiffies; + while (time_before_eq(jiffies, timeout)) { + status = inl(io + SIS_AC97_STATUS); + if (status & SIS_AC97_STATUS_CODEC_READY) + sis->codecs_present |= SIS_PRIMARY_CODEC_PRESENT; + if (status & SIS_AC97_STATUS_CODEC2_READY) + sis->codecs_present |= SIS_SECONDARY_CODEC_PRESENT; + if (status & SIS_AC97_STATUS_CODEC3_READY) + sis->codecs_present |= SIS_TERTIARY_CODEC_PRESENT; + + if (sis->codecs_present == codecs) + break; + + msleep(1); + } + + /* All done, check for errors. */ - outl(SIS_AC97_SEMA_RELEASE, io + SIS_AC97_SEMA); - if (!sis->codecs_present || !count) + if (!sis->codecs_present) { + printk(KERN_ERR "sis7019: could not find any codecs\n"); return -EIO; + } + + if (sis->codecs_present != codecs) { + printk(KERN_WARNING "sis7019: missing codecs, found %0x, expected %0x\n", + sis->codecs_present, codecs); + } /* Let the hardware know that the audio driver is alive, * and enable PCM slots on the AC-link for L/R playback (3 & 4) and @@ -1390,6 +1421,17 @@ static int __devinit snd_sis7019_probe(struct pci_dev *pci, if (!enable) goto error_out; + /* The user can specify which codecs should be present so that we + * can wait for them to show up if they are slow to recover from + * the AC97 cold reset. We default to a single codec, the primary. + * + * We assume that SIS_PRIMARY_*_PRESENT matches bits 0-2. + */ + codecs &= SIS_PRIMARY_CODEC_PRESENT | SIS_SECONDARY_CODEC_PRESENT | + SIS_TERTIARY_CODEC_PRESENT; + if (!codecs) + codecs = SIS_PRIMARY_CODEC_PRESENT; + rc = snd_card_create(index, id, THIS_MODULE, sizeof(*sis), &card); if (rc < 0) goto error_out; -- cgit