diff options
author | Takashi Iwai <tiwai@suse.de> | 2013-01-23 08:31:34 +0100 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2013-01-23 08:31:34 +0100 |
commit | e152f18027552eb34006b35347e72bc805783027 (patch) | |
tree | ac9765e68597c08c24de447f46bb3e04d9881e1b /sound | |
parent | 49ba4f94bddb7f5272c4596d505f94355cc3fbd2 (diff) | |
parent | 42c364ace52ae6b4699105b39f2559c256b6cd4c (diff) | |
download | talos-op-linux-e152f18027552eb34006b35347e72bc805783027.tar.gz talos-op-linux-e152f18027552eb34006b35347e72bc805783027.zip |
Merge branch 'for-linus' into for-next
This is a preliminary merge before the upcoming merge of generic parser
branch.
Diffstat (limited to 'sound')
30 files changed, 353 insertions, 169 deletions
diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/arm/pxa2xx-ac97-lib.c index 6fc0ae90e5b1..fff7753e35c1 100644 --- a/sound/arm/pxa2xx-ac97-lib.c +++ b/sound/arm/pxa2xx-ac97-lib.c @@ -18,6 +18,7 @@ #include <linux/delay.h> #include <linux/module.h> #include <linux/io.h> +#include <linux/gpio.h> #include <sound/ac97_codec.h> #include <sound/pxa2xx-lib.h> @@ -148,6 +149,8 @@ static inline void pxa_ac97_warm_pxa27x(void) static inline void pxa_ac97_cold_pxa27x(void) { + unsigned int timeout; + GCR &= GCR_COLD_RST; /* clear everything but nCRST */ GCR &= ~GCR_COLD_RST; /* then assert nCRST */ @@ -157,8 +160,10 @@ static inline void pxa_ac97_cold_pxa27x(void) clk_enable(ac97conf_clk); udelay(5); clk_disable(ac97conf_clk); - GCR = GCR_COLD_RST; - udelay(50); + GCR = GCR_COLD_RST | GCR_WARM_RST; + timeout = 100; /* wait for the codec-ready bit to be set */ + while (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--) + mdelay(1); } #endif @@ -340,8 +345,21 @@ int pxa2xx_ac97_hw_probe(struct platform_device *dev) } if (cpu_is_pxa27x()) { - /* Use GPIO 113 as AC97 Reset on Bulverde */ + /* + * This gpio is needed for a work-around to a bug in the ac97 + * controller during warm reset. The direction and level is set + * here so that it is an output driven high when switching from + * AC97_nRESET alt function to generic gpio. + */ + ret = gpio_request_one(reset_gpio, GPIOF_OUT_INIT_HIGH, + "pxa27x ac97 reset"); + if (ret < 0) { + pr_err("%s: gpio_request_one() failed: %d\n", + __func__, ret); + goto err_conf; + } pxa27x_assert_ac97reset(reset_gpio, 0); + ac97conf_clk = clk_get(&dev->dev, "AC97CONFCLK"); if (IS_ERR(ac97conf_clk)) { ret = PTR_ERR(ac97conf_clk); @@ -384,6 +402,8 @@ EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_probe); void pxa2xx_ac97_hw_remove(struct platform_device *dev) { + if (cpu_is_pxa27x()) + gpio_free(reset_gpio); GCR |= GCR_ACLINK_OFF; free_irq(IRQ_AC97, NULL); if (ac97conf_clk) { diff --git a/sound/oss/pas2_card.c b/sound/oss/pas2_card.c index dabf8a871dcc..7004e24d209f 100644 --- a/sound/oss/pas2_card.c +++ b/sound/oss/pas2_card.c @@ -333,6 +333,11 @@ static void __init attach_pas_card(struct address_info *hw_config) { char temp[100]; + if (pas_model < 0 || + pas_model >= ARRAY_SIZE(pas_model_names)) { + printk(KERN_ERR "pas2 unrecognized model.\n"); + return; + } sprintf(temp, "%s rev %d", pas_model_names[(int) pas_model], pas_read(0x2789)); diff --git a/sound/pci/au88x0/au88x0_synth.c b/sound/pci/au88x0/au88x0_synth.c index 2805e34bd41d..8bef47311e45 100644 --- a/sound/pci/au88x0/au88x0_synth.c +++ b/sound/pci/au88x0/au88x0_synth.c @@ -58,7 +58,7 @@ static void vortex_wt_setdsout(vortex_t * vortex, u32 wt, int en) if (en) temp |= (1 << (wt & 0x1f)); else - temp &= (1 << ~(wt & 0x1f)); + temp &= ~(1 << (wt & 0x1f)); hwwrite(vortex->mmio, WT_DSREG((wt >= 0x20) ? 1 : 0), temp); } diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 8353c77536ac..b8fb0a5adb9b 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -2531,7 +2531,7 @@ static int vmaster_mute_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { static const char * const texts[] = { - "Off", "On", "Follow Master" + "On", "Off", "Follow Master" }; unsigned int index; diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 988323577834..78e954a1c12a 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -573,9 +573,12 @@ enum { #define AZX_DCAPS_PM_RUNTIME (1 << 26) /* runtime PM support */ /* quirks for Intel PCH */ -#define AZX_DCAPS_INTEL_PCH \ +#define AZX_DCAPS_INTEL_PCH_NOPM \ (AZX_DCAPS_SCH_SNOOP | AZX_DCAPS_BUFSIZE | \ - AZX_DCAPS_COUNT_LPIB_DELAY | AZX_DCAPS_PM_RUNTIME) + AZX_DCAPS_COUNT_LPIB_DELAY) + +#define AZX_DCAPS_INTEL_PCH \ + (AZX_DCAPS_INTEL_PCH_NOPM | AZX_DCAPS_PM_RUNTIME) /* quirks for ATI SB / AMD Hudson */ #define AZX_DCAPS_PRESET_ATI_SB \ @@ -3588,13 +3591,13 @@ static void azx_remove(struct pci_dev *pci) static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { /* CPT */ { PCI_DEVICE(0x8086, 0x1c20), - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, + .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM }, /* PBG */ { PCI_DEVICE(0x8086, 0x1d20), - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, + .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM }, /* Panther Point */ { PCI_DEVICE(0x8086, 0x1e20), - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, + .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM }, /* Lynx Point */ { PCI_DEVICE(0x8086, 0x8c20), .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 60890bfecc19..009b77a693cf 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -558,24 +558,12 @@ static int conexant_build_controls(struct hda_codec *codec) return 0; } -#ifdef CONFIG_PM -static int conexant_suspend(struct hda_codec *codec) -{ - snd_hda_shutup_pins(codec); - return 0; -} -#endif - static const struct hda_codec_ops conexant_patch_ops = { .build_controls = conexant_build_controls, .build_pcms = conexant_build_pcms, .init = conexant_init, .free = conexant_free, .set_power_state = conexant_set_power, -#ifdef CONFIG_PM - .suspend = conexant_suspend, -#endif - .reboot_notify = snd_hda_shutup_pins, }; #ifdef CONFIG_SND_HDA_INPUT_BEEP @@ -4405,10 +4393,6 @@ static const struct hda_codec_ops cx_auto_patch_ops = { .init = cx_auto_init, .free = conexant_free, .unsol_event = snd_hda_jack_unsol_event, -#ifdef CONFIG_PM - .suspend = conexant_suspend, -#endif - .reboot_notify = snd_hda_shutup_pins, }; /* @@ -4652,6 +4636,12 @@ static const struct hda_codec_preset snd_hda_preset_conexant[] = { .patch = patch_conexant_auto }, { .id = 0x14f15111, .name = "CX20753/4", .patch = patch_conexant_auto }, + { .id = 0x14f15113, .name = "CX20755", + .patch = patch_conexant_auto }, + { .id = 0x14f15114, .name = "CX20756", + .patch = patch_conexant_auto }, + { .id = 0x14f15115, .name = "CX20757", + .patch = patch_conexant_auto }, {} /* terminator */ }; @@ -4675,6 +4665,9 @@ MODULE_ALIAS("snd-hda-codec-id:14f150b9"); MODULE_ALIAS("snd-hda-codec-id:14f1510f"); MODULE_ALIAS("snd-hda-codec-id:14f15110"); MODULE_ALIAS("snd-hda-codec-id:14f15111"); +MODULE_ALIAS("snd-hda-codec-id:14f15113"); +MODULE_ALIAS("snd-hda-codec-id:14f15114"); +MODULE_ALIAS("snd-hda-codec-id:14f15115"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Conexant HD-audio codec"); diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index b6c21ea187ca..807a2aa1ff38 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -1502,7 +1502,7 @@ static int hdmi_chmap_ctl_put(struct snd_kcontrol *kcontrol, ctl_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); substream = snd_pcm_chmap_substream(info, ctl_idx); if (!substream || !substream->runtime) - return -EBADFD; + return 0; /* just for avoiding error from alsactl restore */ switch (substream->runtime->status->state) { case SNDRV_PCM_STATE_OPEN: case SNDRV_PCM_STATE_SETUP: diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 6ee34593774a..cf3886171109 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -5817,6 +5817,9 @@ enum { ALC269_TYPE_ALC269VB, ALC269_TYPE_ALC269VC, ALC269_TYPE_ALC269VD, + ALC269_TYPE_ALC280, + ALC269_TYPE_ALC282, + ALC269_TYPE_ALC284, }; /* @@ -5833,10 +5836,13 @@ static int alc269_parse_auto_config(struct hda_codec *codec) switch (spec->codec_variant) { case ALC269_TYPE_ALC269VA: case ALC269_TYPE_ALC269VC: + case ALC269_TYPE_ALC280: + case ALC269_TYPE_ALC284: ssids = alc269va_ssids; break; case ALC269_TYPE_ALC269VB: case ALC269_TYPE_ALC269VD: + case ALC269_TYPE_ALC282: ssids = alc269_ssids; break; default: @@ -5992,6 +5998,30 @@ static void alc269_fixup_quanta_mute(struct hda_codec *codec, spec->automute_hook = alc269_quanta_automute; } +/* update mute-LED according to the speaker mute state via mic1 VREF pin */ +static void alc269_fixup_mic1_mute_hook(void *private_data, int enabled) +{ + struct hda_codec *codec = private_data; + unsigned int pinval = AC_PINCTL_IN_EN + (enabled ? + AC_PINCTL_VREF_HIZ : AC_PINCTL_VREF_80); + snd_hda_set_pin_ctl_cache(codec, 0x18, pinval); +} + +static void alc269_fixup_mic1_mute(struct hda_codec *codec, + const struct alc_fixup *fix, int action) +{ + struct alc_spec *spec = codec->spec; + switch (action) { + case ALC_FIXUP_ACT_BUILD: + spec->vmaster_mute.hook = alc269_fixup_mic1_mute_hook; + snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute, true); + /* fallthru */ + case ALC_FIXUP_ACT_INIT: + snd_hda_sync_vmaster_hook(&spec->vmaster_mute); + break; + } +} + /* update mute-LED according to the speaker mute state via mic2 VREF pin */ static void alc269_fixup_mic2_mute_hook(void *private_data, int enabled) { @@ -6043,6 +6073,7 @@ enum { ALC269_FIXUP_DMIC, ALC269VB_FIXUP_AMIC, ALC269VB_FIXUP_DMIC, + ALC269_FIXUP_MIC1_MUTE_LED, ALC269_FIXUP_MIC2_MUTE_LED, ALC269_FIXUP_INV_DMIC, ALC269_FIXUP_LENOVO_DOCK, @@ -6171,6 +6202,10 @@ static const struct alc_fixup alc269_fixups[] = { { } }, }, + [ALC269_FIXUP_MIC1_MUTE_LED] = { + .type = ALC_FIXUP_FUNC, + .v.func = alc269_fixup_mic1_mute, + }, [ALC269_FIXUP_MIC2_MUTE_LED] = { .type = ALC_FIXUP_FUNC, .v.func = alc269_fixup_mic2_mute, @@ -6215,6 +6250,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1025, 0x029b, "Acer 1810TZ", ALC269_FIXUP_INV_DMIC), SND_PCI_QUIRK(0x1025, 0x0349, "Acer AOD260", ALC269_FIXUP_INV_DMIC), SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_MIC2_MUTE_LED), + SND_PCI_QUIRK(0x103c, 0x1972, "HP Pavilion 17", ALC269_FIXUP_MIC1_MUTE_LED), + SND_PCI_QUIRK(0x103c, 0x1977, "HP Pavilion 14", ALC269_FIXUP_MIC1_MUTE_LED), SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_DMIC), SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_DMIC), SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW), @@ -6229,6 +6266,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO), SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z), + SND_PCI_QUIRK(0x1025, 0x0740, "Acer AO725", ALC271_FIXUP_HP_GATE_MIC_JACK), SND_PCI_QUIRK(0x1025, 0x0742, "Acer AO756", ALC271_FIXUP_HP_GATE_MIC_JACK), SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC), SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK), @@ -6370,7 +6408,8 @@ static int patch_alc269(struct hda_codec *codec) alc_auto_parse_customize_define(codec); - if (codec->vendor_id == 0x10ec0269) { + switch (codec->vendor_id) { + case 0x10ec0269: spec->codec_variant = ALC269_TYPE_ALC269VA; switch (alc_get_coef0(codec) & 0x00f0) { case 0x0010: @@ -6395,6 +6434,20 @@ static int patch_alc269(struct hda_codec *codec) goto error; spec->init_hook = alc269_fill_coef; alc269_fill_coef(codec); + break; + + case 0x10ec0280: + case 0x10ec0290: + spec->codec_variant = ALC269_TYPE_ALC280; + break; + case 0x10ec0282: + case 0x10ec0283: + spec->codec_variant = ALC269_TYPE_ALC282; + break; + case 0x10ec0284: + case 0x10ec0292: + spec->codec_variant = ALC269_TYPE_ALC284; + break; } /* automatic parse from the BIOS config */ @@ -7099,6 +7152,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = { { .id = 0x10ec0280, .name = "ALC280", .patch = patch_alc269 }, { .id = 0x10ec0282, .name = "ALC282", .patch = patch_alc269 }, { .id = 0x10ec0283, .name = "ALC283", .patch = patch_alc269 }, + { .id = 0x10ec0284, .name = "ALC284", .patch = patch_alc269 }, { .id = 0x10ec0290, .name = "ALC290", .patch = patch_alc269 }, { .id = 0x10ec0292, .name = "ALC292", .patch = patch_alc269 }, { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660", diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 6e02e064d7b4..223c3d9cc69e 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -441,6 +441,7 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); */ /* status */ #define HDSPM_AES32_wcLock 0x0200000 +#define HDSPM_AES32_wcSync 0x0100000 #define HDSPM_AES32_wcFreq_bit 22 /* (status >> HDSPM_AES32_wcFreq_bit) & 0xF gives WC frequency (cf function HDSPM_bit2freq */ @@ -3467,10 +3468,12 @@ static int hdspm_wc_sync_check(struct hdspm *hdspm) switch (hdspm->io_type) { case AES32: status = hdspm_read(hdspm, HDSPM_statusRegister); - if (status & HDSPM_wcSync) - return 2; - else if (status & HDSPM_wcLock) - return 1; + if (status & HDSPM_AES32_wcLock) { + if (status & HDSPM_AES32_wcSync) + return 2; + else + return 1; + } return 0; break; @@ -4658,6 +4661,7 @@ snd_hdspm_proc_read_aes32(struct snd_info_entry * entry, unsigned int status; unsigned int status2; unsigned int timecode; + unsigned int wcLock, wcSync; int pref_syncref; char *autosync_ref; int x; @@ -4751,8 +4755,11 @@ snd_hdspm_proc_read_aes32(struct snd_info_entry * entry, snd_iprintf(buffer, "--- Status:\n"); + wcLock = status & HDSPM_AES32_wcLock; + wcSync = wcLock && (status & HDSPM_AES32_wcSync); + snd_iprintf(buffer, "Word: %s Frequency: %d\n", - (status & HDSPM_AES32_wcLock) ? "Sync " : "No Lock", + (wcLock) ? (wcSync ? "Sync " : "Lock ") : "No Lock", HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF)); for (x = 0; x < 8; x++) { diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index adf397b9d0e6..1d8bb5917594 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -446,15 +446,9 @@ static int arizona_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) case SND_SOC_DAIFMT_DSP_A: mode = 0; break; - case SND_SOC_DAIFMT_DSP_B: - mode = 1; - break; case SND_SOC_DAIFMT_I2S: mode = 2; break; - case SND_SOC_DAIFMT_LEFT_J: - mode = 3; - break; default: arizona_aif_err(dai, "Unsupported DAI format %d\n", fmt & SND_SOC_DAIFMT_FORMAT_MASK); @@ -714,7 +708,8 @@ static int arizona_hw_params(struct snd_pcm_substream *substream, snd_soc_update_bits(codec, ARIZONA_ASYNC_SAMPLE_RATE_1, ARIZONA_ASYNC_SAMPLE_RATE_MASK, sr_val); snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL, - ARIZONA_AIF1_RATE_MASK, 8); + ARIZONA_AIF1_RATE_MASK, + 8 << ARIZONA_AIF1_RATE_SHIFT); break; default: arizona_aif_err(dai, "Invalid clock %d\n", dai_priv->clk); diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h index 41dae1ed3b71..4deebeb07177 100644 --- a/sound/soc/codecs/arizona.h +++ b/sound/soc/codecs/arizona.h @@ -34,15 +34,15 @@ #define ARIZONA_FLL_SRC_MCLK1 0 #define ARIZONA_FLL_SRC_MCLK2 1 -#define ARIZONA_FLL_SRC_SLIMCLK 2 -#define ARIZONA_FLL_SRC_FLL1 3 -#define ARIZONA_FLL_SRC_FLL2 4 -#define ARIZONA_FLL_SRC_AIF1BCLK 5 -#define ARIZONA_FLL_SRC_AIF2BCLK 6 -#define ARIZONA_FLL_SRC_AIF3BCLK 7 -#define ARIZONA_FLL_SRC_AIF1LRCLK 8 -#define ARIZONA_FLL_SRC_AIF2LRCLK 9 -#define ARIZONA_FLL_SRC_AIF3LRCLK 10 +#define ARIZONA_FLL_SRC_SLIMCLK 3 +#define ARIZONA_FLL_SRC_FLL1 4 +#define ARIZONA_FLL_SRC_FLL2 5 +#define ARIZONA_FLL_SRC_AIF1BCLK 8 +#define ARIZONA_FLL_SRC_AIF2BCLK 9 +#define ARIZONA_FLL_SRC_AIF3BCLK 10 +#define ARIZONA_FLL_SRC_AIF1LRCLK 12 +#define ARIZONA_FLL_SRC_AIF2LRCLK 13 +#define ARIZONA_FLL_SRC_AIF3LRCLK 14 #define ARIZONA_MIXER_VOL_MASK 0x00FE #define ARIZONA_MIXER_VOL_SHIFT 1 diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c index 4f1127935fdf..ac8742a1f25a 100644 --- a/sound/soc/codecs/cs4271.c +++ b/sound/soc/codecs/cs4271.c @@ -474,16 +474,16 @@ static int cs4271_probe(struct snd_soc_codec *codec) struct cs4271_platform_data *cs4271plat = codec->dev->platform_data; int ret; int gpio_nreset = -EINVAL; - int amutec_eq_bmutec = 0; + bool amutec_eq_bmutec = false; #ifdef CONFIG_OF if (of_match_device(cs4271_dt_ids, codec->dev)) { gpio_nreset = of_get_named_gpio(codec->dev->of_node, "reset-gpio", 0); - if (!of_get_property(codec->dev->of_node, + if (of_get_property(codec->dev->of_node, "cirrus,amutec-eq-bmutec", NULL)) - amutec_eq_bmutec = 1; + amutec_eq_bmutec = true; } #endif diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index 99bb1c69499e..9811a5478c87 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c @@ -737,7 +737,7 @@ static const struct cs42l52_clk_para clk_map_table[] = { static int cs42l52_get_clk(int mclk, int rate) { - int i, ret = 0; + int i, ret = -EINVAL; u_int mclk1, mclk2 = 0; for (i = 0; i < ARRAY_SIZE(clk_map_table); i++) { @@ -749,8 +749,6 @@ static int cs42l52_get_clk(int mclk, int rate) } } } - if (ret > ARRAY_SIZE(clk_map_table)) - return -EINVAL; return ret; } diff --git a/sound/soc/codecs/lm49453.c b/sound/soc/codecs/lm49453.c index d75257d40a49..e19490cfb3a8 100644 --- a/sound/soc/codecs/lm49453.c +++ b/sound/soc/codecs/lm49453.c @@ -111,9 +111,9 @@ static struct reg_default lm49453_reg_defs[] = { { 101, 0x00 }, { 102, 0x00 }, { 103, 0x01 }, - { 105, 0x01 }, - { 106, 0x00 }, - { 107, 0x01 }, + { 104, 0x01 }, + { 105, 0x00 }, + { 106, 0x01 }, { 107, 0x00 }, { 108, 0x00 }, { 109, 0x00 }, @@ -163,56 +163,25 @@ static struct reg_default lm49453_reg_defs[] = { { 184, 0x00 }, { 185, 0x00 }, { 186, 0x00 }, - { 189, 0x00 }, + { 187, 0x00 }, { 188, 0x00 }, - { 194, 0x00 }, - { 195, 0x00 }, - { 196, 0x00 }, - { 197, 0x00 }, - { 200, 0x00 }, - { 201, 0x00 }, - { 202, 0x00 }, - { 203, 0x00 }, - { 204, 0x00 }, - { 205, 0x00 }, - { 208, 0x00 }, + { 189, 0x00 }, + { 208, 0x06 }, { 209, 0x00 }, - { 210, 0x00 }, - { 211, 0x00 }, - { 213, 0x00 }, - { 214, 0x00 }, - { 215, 0x00 }, - { 216, 0x00 }, - { 217, 0x00 }, - { 218, 0x00 }, - { 219, 0x00 }, + { 210, 0x08 }, + { 211, 0x54 }, + { 212, 0x14 }, + { 213, 0x0d }, + { 214, 0x0d }, + { 215, 0x14 }, + { 216, 0x60 }, { 221, 0x00 }, { 222, 0x00 }, + { 223, 0x00 }, { 224, 0x00 }, - { 225, 0x00 }, - { 226, 0x00 }, - { 227, 0x00 }, - { 228, 0x00 }, - { 229, 0x00 }, - { 230, 0x13 }, - { 231, 0x00 }, - { 232, 0x80 }, - { 233, 0x0C }, - { 234, 0xDD }, - { 235, 0x00 }, - { 236, 0x04 }, - { 237, 0x00 }, - { 238, 0x00 }, - { 239, 0x00 }, - { 240, 0x00 }, - { 241, 0x00 }, - { 242, 0x00 }, - { 243, 0x00 }, - { 244, 0x00 }, - { 245, 0x00 }, { 248, 0x00 }, { 249, 0x00 }, - { 254, 0x00 }, + { 250, 0x00 }, { 255, 0x00 }, }; @@ -525,36 +494,41 @@ SOC_DAPM_SINGLE("Port2_2 Switch", LM49453_P0_PORT2_TX2_REG, 7, 1, 0), }; /* TLV Declarations */ -static const DECLARE_TLV_DB_SCALE(digital_tlv, -7650, 150, 1); -static const DECLARE_TLV_DB_SCALE(port_tlv, 0, 600, 0); +static const DECLARE_TLV_DB_SCALE(adc_dac_tlv, -7650, 150, 1); +static const DECLARE_TLV_DB_SCALE(mic_tlv, 0, 200, 1); +static const DECLARE_TLV_DB_SCALE(port_tlv, -1800, 600, 0); +static const DECLARE_TLV_DB_SCALE(stn_tlv, -7200, 150, 0); static const struct snd_kcontrol_new lm49453_sidetone_mixer_controls[] = { /* Sidetone supports mono only */ SOC_DAPM_SINGLE_TLV("Sidetone ADCL Volume", LM49453_P0_STN_VOL_ADCL_REG, - 0, 0x3F, 0, digital_tlv), + 0, 0x3F, 0, stn_tlv), SOC_DAPM_SINGLE_TLV("Sidetone ADCR Volume", LM49453_P0_STN_VOL_ADCR_REG, - 0, 0x3F, 0, digital_tlv), + 0, 0x3F, 0, stn_tlv), SOC_DAPM_SINGLE_TLV("Sidetone DMIC1L Volume", LM49453_P0_STN_VOL_DMIC1L_REG, - 0, 0x3F, 0, digital_tlv), + 0, 0x3F, 0, stn_tlv), SOC_DAPM_SINGLE_TLV("Sidetone DMIC1R Volume", LM49453_P0_STN_VOL_DMIC1R_REG, - 0, 0x3F, 0, digital_tlv), + 0, 0x3F, 0, stn_tlv), SOC_DAPM_SINGLE_TLV("Sidetone DMIC2L Volume", LM49453_P0_STN_VOL_DMIC2L_REG, - 0, 0x3F, 0, digital_tlv), + 0, 0x3F, 0, stn_tlv), SOC_DAPM_SINGLE_TLV("Sidetone DMIC2R Volume", LM49453_P0_STN_VOL_DMIC2R_REG, - 0, 0x3F, 0, digital_tlv), + 0, 0x3F, 0, stn_tlv), }; static const struct snd_kcontrol_new lm49453_snd_controls[] = { /* mic1 and mic2 supports mono only */ - SOC_SINGLE_TLV("Mic1 Volume", LM49453_P0_ADC_LEVELL_REG, 0, 6, - 0, digital_tlv), - SOC_SINGLE_TLV("Mic2 Volume", LM49453_P0_ADC_LEVELR_REG, 0, 6, - 0, digital_tlv), + SOC_SINGLE_TLV("Mic1 Volume", LM49453_P0_MICL_REG, 0, 15, 0, mic_tlv), + SOC_SINGLE_TLV("Mic2 Volume", LM49453_P0_MICR_REG, 0, 15, 0, mic_tlv), + + SOC_SINGLE_TLV("ADCL Volume", LM49453_P0_ADC_LEVELL_REG, 0, 63, + 0, adc_dac_tlv), + SOC_SINGLE_TLV("ADCR Volume", LM49453_P0_ADC_LEVELR_REG, 0, 63, + 0, adc_dac_tlv), SOC_DOUBLE_R_TLV("DMIC1 Volume", LM49453_P0_DMIC1_LEVELL_REG, - LM49453_P0_DMIC1_LEVELR_REG, 0, 6, 0, digital_tlv), + LM49453_P0_DMIC1_LEVELR_REG, 0, 63, 0, adc_dac_tlv), SOC_DOUBLE_R_TLV("DMIC2 Volume", LM49453_P0_DMIC2_LEVELL_REG, - LM49453_P0_DMIC2_LEVELR_REG, 0, 6, 0, digital_tlv), + LM49453_P0_DMIC2_LEVELR_REG, 0, 63, 0, adc_dac_tlv), SOC_DAPM_ENUM("Mic2Mode", lm49453_mic2mode_enum), SOC_DAPM_ENUM("DMIC12 SRC", lm49453_dmic12_cfg_enum), @@ -569,16 +543,16 @@ static const struct snd_kcontrol_new lm49453_snd_controls[] = { 2, 1, 0), SOC_DOUBLE_R_TLV("DAC HP Volume", LM49453_P0_DAC_HP_LEVELL_REG, - LM49453_P0_DAC_HP_LEVELR_REG, 0, 6, 0, digital_tlv), + LM49453_P0_DAC_HP_LEVELR_REG, 0, 63, 0, adc_dac_tlv), SOC_DOUBLE_R_TLV("DAC LO Volume", LM49453_P0_DAC_LO_LEVELL_REG, - LM49453_P0_DAC_LO_LEVELR_REG, 0, 6, 0, digital_tlv), + LM49453_P0_DAC_LO_LEVELR_REG, 0, 63, 0, adc_dac_tlv), SOC_DOUBLE_R_TLV("DAC LS Volume", LM49453_P0_DAC_LS_LEVELL_REG, - LM49453_P0_DAC_LS_LEVELR_REG, 0, 6, 0, digital_tlv), + LM49453_P0_DAC_LS_LEVELR_REG, 0, 63, 0, adc_dac_tlv), SOC_DOUBLE_R_TLV("DAC HA Volume", LM49453_P0_DAC_HA_LEVELL_REG, - LM49453_P0_DAC_HA_LEVELR_REG, 0, 6, 0, digital_tlv), + LM49453_P0_DAC_HA_LEVELR_REG, 0, 63, 0, adc_dac_tlv), SOC_SINGLE_TLV("EP Volume", LM49453_P0_DAC_LS_LEVELL_REG, - 0, 6, 0, digital_tlv), + 0, 63, 0, adc_dac_tlv), SOC_SINGLE_TLV("PORT1_1_RX_LVL Volume", LM49453_P0_PORT1_RX_LVL1_REG, 0, 3, 0, port_tlv), @@ -1218,7 +1192,7 @@ static int lm49453_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) } snd_soc_update_bits(codec, LM49453_P0_AUDIO_PORT1_BASIC_REG, - LM49453_AUDIO_PORT1_BASIC_FMT_MASK|BIT(1)|BIT(5), + LM49453_AUDIO_PORT1_BASIC_FMT_MASK|BIT(0)|BIT(5), (aif_val | mode | clk_phase)); snd_soc_write(codec, LM49453_P0_AUDIO_PORT1_RX_MSB_REG, clk_shift); diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index cb1675cd8e1c..92bbfec9b107 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -401,7 +401,7 @@ static const struct snd_kcontrol_new sgtl5000_snd_controls[] = { 5, 1, 0), SOC_SINGLE_TLV("Mic Volume", SGTL5000_CHIP_MIC_CTRL, - 0, 4, 0, mic_gain_tlv), + 0, 3, 0, mic_gain_tlv), }; /* mute the codec used by alsa core */ @@ -1344,7 +1344,7 @@ static int sgtl5000_probe(struct snd_soc_codec *codec) SGTL5000_HP_ZCD_EN | SGTL5000_ADC_ZCD_EN); - snd_soc_write(codec, SGTL5000_CHIP_MIC_CTRL, 0); + snd_soc_write(codec, SGTL5000_CHIP_MIC_CTRL, 2); /* * disable DAP diff --git a/sound/soc/codecs/sta529.c b/sound/soc/codecs/sta529.c index ab355c4f0b2d..40c07be9b581 100644 --- a/sound/soc/codecs/sta529.c +++ b/sound/soc/codecs/sta529.c @@ -74,9 +74,10 @@ SNDRV_PCM_FMTBIT_S32_LE) #define S2PC_VALUE 0x98 #define CLOCK_OUT 0x60 -#define LEFT_J_DATA_FORMAT 0x10 -#define I2S_DATA_FORMAT 0x12 -#define RIGHT_J_DATA_FORMAT 0x14 +#define DATA_FORMAT_MSK 0x0E +#define LEFT_J_DATA_FORMAT 0x00 +#define I2S_DATA_FORMAT 0x02 +#define RIGHT_J_DATA_FORMAT 0x04 #define CODEC_MUTE_VAL 0x80 #define POWER_CNTLMSAK 0x40 @@ -289,7 +290,7 @@ static int sta529_set_dai_fmt(struct snd_soc_dai *codec_dai, u32 fmt) return -EINVAL; } - snd_soc_update_bits(codec, STA529_S2PCFG0, 0x0D, mode); + snd_soc_update_bits(codec, STA529_S2PCFG0, DATA_FORMAT_MSK, mode); return 0; } diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c index 1cbe88f01d63..12bcae63a7f0 100644 --- a/sound/soc/codecs/wm2000.c +++ b/sound/soc/codecs/wm2000.c @@ -209,9 +209,9 @@ static int wm2000_power_up(struct i2c_client *i2c, int analogue) ret = wm2000_read(i2c, WM2000_REG_SPEECH_CLARITY); if (wm2000->speech_clarity) - ret &= ~WM2000_SPEECH_CLARITY; - else ret |= WM2000_SPEECH_CLARITY; + else + ret &= ~WM2000_SPEECH_CLARITY; wm2000_write(i2c, WM2000_REG_SPEECH_CLARITY, ret); wm2000_write(i2c, WM2000_REG_SYS_START0, 0x33); diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index afcf31df77e0..e6cefe1ac677 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c @@ -1566,15 +1566,9 @@ static int wm2200_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) case SND_SOC_DAIFMT_DSP_A: fmt_val = 0; break; - case SND_SOC_DAIFMT_DSP_B: - fmt_val = 1; - break; case SND_SOC_DAIFMT_I2S: fmt_val = 2; break; - case SND_SOC_DAIFMT_LEFT_J: - fmt_val = 3; - break; default: dev_err(codec->dev, "Unsupported DAI format %d\n", fmt & SND_SOC_DAIFMT_FORMAT_MASK); @@ -1626,7 +1620,7 @@ static int wm2200_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) WM2200_AIF1TX_LRCLK_MSTR | WM2200_AIF1TX_LRCLK_INV, lrclk); snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_5, - WM2200_AIF1_FMT_MASK << 1, fmt_val << 1); + WM2200_AIF1_FMT_MASK, fmt_val); return 0; } diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index 5a5f36936235..54397a508073 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c @@ -1279,15 +1279,9 @@ static int wm5100_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) case SND_SOC_DAIFMT_DSP_A: mask = 0; break; - case SND_SOC_DAIFMT_DSP_B: - mask = 1; - break; case SND_SOC_DAIFMT_I2S: mask = 2; break; - case SND_SOC_DAIFMT_LEFT_J: - mask = 3; - break; default: dev_err(codec->dev, "Unsupported DAI format %d\n", fmt & SND_SOC_DAIFMT_FORMAT_MASK); diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index 688ade080589..7a9048dad1cd 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -36,6 +36,9 @@ struct wm5102_priv { struct arizona_priv core; struct arizona_fll fll[2]; + + unsigned int spk_ena:2; + unsigned int spk_ena_pending:1; }; static DECLARE_TLV_DB_SCALE(ana_tlv, 0, 100, 0); @@ -787,6 +790,47 @@ ARIZONA_MIXER_CONTROLS("AIF3TX1", ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("AIF3TX2", ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE), }; +static int wm5102_spk_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_codec *codec = w->codec; + struct arizona *arizona = dev_get_drvdata(codec->dev->parent); + struct wm5102_priv *wm5102 = snd_soc_codec_get_drvdata(codec); + + if (arizona->rev < 1) + return 0; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + if (!wm5102->spk_ena) { + snd_soc_write(codec, 0x4f5, 0x25a); + wm5102->spk_ena_pending = true; + } + break; + case SND_SOC_DAPM_POST_PMU: + if (wm5102->spk_ena_pending) { + msleep(75); + snd_soc_write(codec, 0x4f5, 0xda); + wm5102->spk_ena_pending = false; + wm5102->spk_ena++; + } + break; + case SND_SOC_DAPM_PRE_PMD: + wm5102->spk_ena--; + if (!wm5102->spk_ena) + snd_soc_write(codec, 0x4f5, 0x25a); + break; + case SND_SOC_DAPM_POST_PMD: + if (!wm5102->spk_ena) + snd_soc_write(codec, 0x4f5, 0x0da); + break; + } + + return 0; +} + + ARIZONA_MIXER_ENUMS(EQ1, ARIZONA_EQ1MIX_INPUT_1_SOURCE); ARIZONA_MIXER_ENUMS(EQ2, ARIZONA_EQ2MIX_INPUT_1_SOURCE); ARIZONA_MIXER_ENUMS(EQ3, ARIZONA_EQ3MIX_INPUT_1_SOURCE); @@ -1034,10 +1078,10 @@ SND_SOC_DAPM_PGA_E("OUT3L", ARIZONA_OUTPUT_ENABLES_1, ARIZONA_OUT3L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_PGA_E("OUT4L", ARIZONA_OUTPUT_ENABLES_1, - ARIZONA_OUT4L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, + ARIZONA_OUT4L_ENA_SHIFT, 0, NULL, 0, wm5102_spk_ev, SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_PGA_E("OUT4R", ARIZONA_OUTPUT_ENABLES_1, - ARIZONA_OUT4R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, + ARIZONA_OUT4R_ENA_SHIFT, 0, NULL, 0, wm5102_spk_ev, SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_PGA_E("OUT5L", ARIZONA_OUTPUT_ENABLES_1, ARIZONA_OUT5L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index ffc89fab96fb..7b198c38f3ef 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -169,6 +169,7 @@ static int wm_adsp_load(struct wm_adsp *dsp) const struct wm_adsp_region *mem; const char *region_name; char *file, *text; + void *buf; unsigned int reg; int regions = 0; int ret, offset, type, sizes; @@ -322,8 +323,18 @@ static int wm_adsp_load(struct wm_adsp *dsp) } if (reg) { - ret = regmap_raw_write(regmap, reg, region->data, + buf = kmemdup(region->data, le32_to_cpu(region->len), + GFP_KERNEL); + if (!buf) { + adsp_err(dsp, "Out of memory\n"); + return -ENOMEM; + } + + ret = regmap_raw_write(regmap, reg, buf, le32_to_cpu(region->len)); + + kfree(buf); + if (ret != 0) { adsp_err(dsp, "%s.%d: Failed to write %d bytes at %d in %s: %d\n", @@ -359,6 +370,7 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp) const char *region_name; int ret, pos, blocks, type, offset, reg; char *file; + void *buf; file = kzalloc(PAGE_SIZE, GFP_KERNEL); if (file == NULL) @@ -426,6 +438,13 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp) } if (reg) { + buf = kmemdup(blk->data, le32_to_cpu(blk->len), + GFP_KERNEL); + if (!buf) { + adsp_err(dsp, "Out of memory\n"); + return -ENOMEM; + } + ret = regmap_raw_write(regmap, reg, blk->data, le32_to_cpu(blk->len)); if (ret != 0) { @@ -433,6 +452,8 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp) "%s.%d: Failed to write to %x in %s\n", file, blocks, reg, region_name); } + + kfree(buf); } pos += le32_to_cpu(blk->len) + sizeof(*blk); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 91d592ff67b7..2370063b5824 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1255,6 +1255,8 @@ static int soc_post_component_init(struct snd_soc_card *card, INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_CAPTURE].fe_clients); ret = device_add(rtd->dev); if (ret < 0) { + /* calling put_device() here to free the rtd->dev */ + put_device(rtd->dev); dev_err(card->dev, "ASoC: failed to register runtime device: %d\n", ret); return ret; @@ -1554,7 +1556,7 @@ static void soc_remove_aux_dev(struct snd_soc_card *card, int num) /* unregister the rtd device */ if (rtd->dev_registered) { device_remove_file(rtd->dev, &dev_attr_codec_reg); - device_del(rtd->dev); + device_unregister(rtd->dev); rtd->dev_registered = 0; } @@ -2917,7 +2919,7 @@ int snd_soc_info_volsw_range(struct snd_kcontrol *kcontrol, platform_max = mc->platform_max; uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; + uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1; uinfo->value.integer.min = 0; uinfo->value.integer.max = platform_max - min; @@ -2941,12 +2943,14 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, (struct soc_mixer_control *)kcontrol->private_value; struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); unsigned int reg = mc->reg; + unsigned int rreg = mc->rreg; unsigned int shift = mc->shift; int min = mc->min; int max = mc->max; unsigned int mask = (1 << fls(max)) - 1; unsigned int invert = mc->invert; unsigned int val, val_mask; + int ret; val = ((ucontrol->value.integer.value[0] + min) & mask); if (invert) @@ -2954,7 +2958,21 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, val_mask = mask << shift; val = val << shift; - return snd_soc_update_bits_locked(codec, reg, val_mask, val); + ret = snd_soc_update_bits_locked(codec, reg, val_mask, val); + if (ret != 0) + return ret; + + if (snd_soc_volsw_is_stereo(mc)) { + val = ((ucontrol->value.integer.value[1] + min) & mask); + if (invert) + val = max - val; + val_mask = mask << shift; + val = val << shift; + + ret = snd_soc_update_bits_locked(codec, rreg, val_mask, val); + } + + return ret; } EXPORT_SYMBOL_GPL(snd_soc_put_volsw_range); @@ -2974,6 +2992,7 @@ int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol, (struct soc_mixer_control *)kcontrol->private_value; struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); unsigned int reg = mc->reg; + unsigned int rreg = mc->rreg; unsigned int shift = mc->shift; int min = mc->min; int max = mc->max; @@ -2988,6 +3007,16 @@ int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol, ucontrol->value.integer.value[0] = ucontrol->value.integer.value[0] - min; + if (snd_soc_volsw_is_stereo(mc)) { + ucontrol->value.integer.value[1] = + (snd_soc_read(codec, rreg) >> shift) & mask; + if (invert) + ucontrol->value.integer.value[1] = + max - ucontrol->value.integer.value[1]; + ucontrol->value.integer.value[1] = + ucontrol->value.integer.value[1] - min; + } + return 0; } EXPORT_SYMBOL_GPL(snd_soc_get_volsw_range); diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index d7711fce119b..cf191e6aebbe 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1243,6 +1243,7 @@ static int dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream) if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) && (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PREPARE) && (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE) && + (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED) && (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP)) continue; diff --git a/sound/usb/midi.c b/sound/usb/midi.c index c183d34842ac..34b9bb7fe87c 100644 --- a/sound/usb/midi.c +++ b/sound/usb/midi.c @@ -2181,10 +2181,6 @@ int snd_usbmidi_create(struct snd_card *card, umidi->usb_protocol_ops = &snd_usbmidi_novation_ops; err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); break; - case QUIRK_MIDI_MBOX2: - umidi->usb_protocol_ops = &snd_usbmidi_midiman_ops; - err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); - break; case QUIRK_MIDI_RAW_BYTES: umidi->usb_protocol_ops = &snd_usbmidi_raw_ops; /* diff --git a/sound/usb/mixer_maps.c b/sound/usb/mixer_maps.c index e71fe55cebef..0e2ed3d05c45 100644 --- a/sound/usb/mixer_maps.c +++ b/sound/usb/mixer_maps.c @@ -179,6 +179,15 @@ static struct usbmix_name_map audigy2nx_map[] = { { 0 } /* terminator */ }; +static struct usbmix_selector_map c400_selectors[] = { + { + .id = 0x80, + .count = 2, + .names = (const char*[]) {"Internal", "SPDIF"} + }, + { 0 } /* terminator */ +}; + static struct usbmix_selector_map audigy2nx_selectors[] = { { .id = 14, /* Capture Source */ @@ -367,6 +376,10 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = { .map = hercules_usb51_map, }, { + .id = USB_ID(0x0763, 0x2030), + .selector_map = c400_selectors, + }, + { .id = USB_ID(0x08bb, 0x2702), .map = linex_map, .ignore_ctl_error = 1, diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 0422b1360af3..15520de1df56 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -1206,7 +1206,7 @@ static int snd_c400_create_mixer(struct usb_mixer_interface *mixer) * are valid they presents mono controls as L and R channels of * stereo. So we provide a good mixer here. */ -struct std_mono_table ebox44_table[] = { +static struct std_mono_table ebox44_table[] = { { .unitid = 4, .control = 1, diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 3a384479e923..b839b60f9858 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -515,6 +515,16 @@ static int configure_sync_endpoint(struct snd_usb_substream *subs) struct snd_usb_substream *sync_subs = &subs->stream->substream[subs->direction ^ 1]; + if (subs->sync_endpoint->type != SND_USB_ENDPOINT_TYPE_DATA || + !subs->stream) + return snd_usb_endpoint_set_params(subs->sync_endpoint, + subs->pcm_format, + subs->channels, + subs->period_bytes, + subs->cur_rate, + subs->cur_audiofmt, + NULL); + /* Try to find the best matching audioformat. */ list_for_each_entry(fp, &sync_subs->fmt_list, list) { int score = match_endpoint_audioformats(fp, subs->cur_audiofmt, diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index cdcf6b45e8a8..64d25a7a4d59 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -50,6 +50,28 @@ } }, +{ + /* Creative BT-D1 */ + USB_DEVICE(0x041e, 0x0005), + .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + .ifnum = 1, + .type = QUIRK_AUDIO_FIXED_ENDPOINT, + .data = &(const struct audioformat) { + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .channels = 2, + .iface = 1, + .altsetting = 1, + .altset_idx = 1, + .endpoint = 0x03, + .ep_attr = USB_ENDPOINT_XFER_ISOC, + .attributes = 0, + .rates = SNDRV_PCM_RATE_CONTINUOUS, + .rate_min = 48000, + .rate_max = 48000, + } + } +}, + /* Creative/Toshiba Multimedia Center SB-0500 */ { USB_DEVICE(0x041e, 0x3048), @@ -2267,7 +2289,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .rate_table = (unsigned int[]) { 44100, 48000, 88200, 96000 }, - .clock = 0x81, + .clock = 0x80, } }, /* Capture */ @@ -2293,7 +2315,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .rate_table = (unsigned int[]) { 44100, 48000, 88200, 96000 }, - .clock = 0x81, + .clock = 0x80, } }, /* MIDI */ @@ -2993,7 +3015,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, { .ifnum = 6, - .type = QUIRK_MIDI_MBOX2, + .type = QUIRK_MIDI_MIDIMAN, .data = &(const struct snd_usb_midi_endpoint_info) { .out_ep = 0x02, .out_cables = 0x0001, diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index f104c68fe1e0..2c971858d6b7 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -306,7 +306,6 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip, [QUIRK_MIDI_YAMAHA] = create_any_midi_quirk, [QUIRK_MIDI_MIDIMAN] = create_any_midi_quirk, [QUIRK_MIDI_NOVATION] = create_any_midi_quirk, - [QUIRK_MIDI_MBOX2] = create_any_midi_quirk, [QUIRK_MIDI_RAW_BYTES] = create_any_midi_quirk, [QUIRK_MIDI_EMAGIC] = create_any_midi_quirk, [QUIRK_MIDI_CME] = create_any_midi_quirk, @@ -388,11 +387,13 @@ static int snd_usb_fasttrackpro_boot_quirk(struct usb_device *dev) * rules */ err = usb_driver_set_configuration(dev, 2); - if (err < 0) { + if (err < 0) snd_printdd("error usb_driver_set_configuration: %d\n", err); - return -ENODEV; - } + /* Always return an error, so that we stop creating a device + that will just be destroyed and recreated with a new + configuration */ + return -ENODEV; } else snd_printk(KERN_INFO "usb-audio: Fast Track Pro config OK\n"); @@ -528,11 +529,11 @@ static void mbox2_setup_48_24_magic(struct usb_device *dev) #define MBOX2_BOOT_LOADING 0x01 /* Hard coded into the device */ #define MBOX2_BOOT_READY 0x02 /* Hard coded into the device */ -int snd_usb_mbox2_boot_quirk(struct usb_device *dev) +static int snd_usb_mbox2_boot_quirk(struct usb_device *dev) { struct usb_host_config *config = dev->actconfig; int err; - u8 bootresponse; + u8 bootresponse[12]; int fwsize; int count; @@ -546,20 +547,20 @@ int snd_usb_mbox2_boot_quirk(struct usb_device *dev) snd_printd("usb-audio: Sending Digidesign Mbox 2 boot sequence...\n"); count = 0; - bootresponse = MBOX2_BOOT_LOADING; - while ((bootresponse == MBOX2_BOOT_LOADING) && (count < 10)) { + bootresponse[0] = MBOX2_BOOT_LOADING; + while ((bootresponse[0] == MBOX2_BOOT_LOADING) && (count < 10)) { msleep(500); /* 0.5 second delay */ snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), /* Control magic - load onboard firmware */ 0x85, 0xc0, 0x0001, 0x0000, &bootresponse, 0x0012); - if (bootresponse == MBOX2_BOOT_READY) + if (bootresponse[0] == MBOX2_BOOT_READY) break; snd_printd("usb-audio: device not ready, resending boot sequence...\n"); count++; } - if (bootresponse != MBOX2_BOOT_READY) { - snd_printk(KERN_ERR "usb-audio: Unknown bootresponse=%d, or timed out, ignoring device.\n", bootresponse); + if (bootresponse[0] != MBOX2_BOOT_READY) { + snd_printk(KERN_ERR "usb-audio: Unknown bootresponse=%d, or timed out, ignoring device.\n", bootresponse[0]); return -ENODEV; } @@ -660,7 +661,6 @@ static int audiophile_skip_setting_quirk(struct snd_usb_audio *chip, return 0; /* keep this altsetting */ } - static int fasttrackpro_skip_setting_quirk(struct snd_usb_audio *chip, int iface, int altno) { @@ -861,6 +861,17 @@ void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep) if ((le16_to_cpu(ep->chip->dev->descriptor.idVendor) == 0x23ba) && ep->type == SND_USB_ENDPOINT_TYPE_SYNC) ep->skip_packets = 4; + + /* + * M-Audio Fast Track C400 - when packets are not skipped, real world + * latency varies by approx. +/- 50 frames (at 96KHz) each time the + * stream is (re)started. When skipping packets 16 at endpoint start + * up, the real world latency is stable within +/- 1 frame (also + * across power cycles). + */ + if (ep->chip->usb_id == USB_ID(0x0763, 0x2030) && + ep->type == SND_USB_ENDPOINT_TYPE_DATA) + ep->skip_packets = 16; } void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe, diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index a8172c119796..1ac3fd9cc5a6 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -76,7 +76,6 @@ enum quirk_type { QUIRK_MIDI_YAMAHA, QUIRK_MIDI_MIDIMAN, QUIRK_MIDI_NOVATION, - QUIRK_MIDI_MBOX2, QUIRK_MIDI_RAW_BYTES, QUIRK_MIDI_EMAGIC, QUIRK_MIDI_CME, |