diff options
Diffstat (limited to 'sound')
33 files changed, 401 insertions, 231 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/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index b8fb0a5adb9b..822df971972c 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -3654,6 +3654,7 @@ static void hda_call_codec_resume(struct hda_codec *codec) hda_set_power_state(codec, AC_PWRST_D0); restore_shutup_pins(codec); hda_exec_init_verbs(codec); + snd_hda_jack_set_dirty_all(codec); if (codec->patch_ops.resume) codec->patch_ops.resume(codec); else { @@ -3665,10 +3666,8 @@ static void hda_call_codec_resume(struct hda_codec *codec) if (codec->jackpoll_interval) hda_jackpoll_work(&codec->jackpoll_work.work); - else { - snd_hda_jack_set_dirty_all(codec); + else snd_hda_jack_report_sync(codec); - } codec->in_pm = 0; snd_hda_power_down(codec); /* flag down before returning */ diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index cca87277baf0..c78286f6e5d8 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 \ @@ -653,29 +656,43 @@ static char *driver_short_names[] = { #define get_azx_dev(substream) (substream->runtime->private_data) #ifdef CONFIG_X86 -static void __mark_pages_wc(struct azx *chip, void *addr, size_t size, bool on) +static void __mark_pages_wc(struct azx *chip, struct snd_dma_buffer *dmab, bool on) { + int pages; + if (azx_snoop(chip)) return; - if (addr && size) { - int pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; + if (!dmab || !dmab->area || !dmab->bytes) + return; + +#ifdef CONFIG_SND_DMA_SGBUF + if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_SG) { + struct snd_sg_buf *sgbuf = dmab->private_data; if (on) - set_memory_wc((unsigned long)addr, pages); + set_pages_array_wc(sgbuf->page_table, sgbuf->pages); else - set_memory_wb((unsigned long)addr, pages); + set_pages_array_wb(sgbuf->page_table, sgbuf->pages); + return; } +#endif + + pages = (dmab->bytes + PAGE_SIZE - 1) >> PAGE_SHIFT; + if (on) + set_memory_wc((unsigned long)dmab->area, pages); + else + set_memory_wb((unsigned long)dmab->area, pages); } static inline void mark_pages_wc(struct azx *chip, struct snd_dma_buffer *buf, bool on) { - __mark_pages_wc(chip, buf->area, buf->bytes, on); + __mark_pages_wc(chip, buf, on); } static inline void mark_runtime_wc(struct azx *chip, struct azx_dev *azx_dev, - struct snd_pcm_runtime *runtime, bool on) + struct snd_pcm_substream *substream, bool on) { if (azx_dev->wc_marked != on) { - __mark_pages_wc(chip, runtime->dma_area, runtime->dma_bytes, on); + __mark_pages_wc(chip, snd_pcm_get_dma_buf(substream), on); azx_dev->wc_marked = on; } } @@ -686,7 +703,7 @@ static inline void mark_pages_wc(struct azx *chip, struct snd_dma_buffer *buf, { } static inline void mark_runtime_wc(struct azx *chip, struct azx_dev *azx_dev, - struct snd_pcm_runtime *runtime, bool on) + struct snd_pcm_substream *substream, bool on) { } #endif @@ -1965,11 +1982,10 @@ static int azx_pcm_hw_params(struct snd_pcm_substream *substream, { struct azx_pcm *apcm = snd_pcm_substream_chip(substream); struct azx *chip = apcm->chip; - struct snd_pcm_runtime *runtime = substream->runtime; struct azx_dev *azx_dev = get_azx_dev(substream); int ret; - mark_runtime_wc(chip, azx_dev, runtime, false); + mark_runtime_wc(chip, azx_dev, substream, false); azx_dev->bufsize = 0; azx_dev->period_bytes = 0; azx_dev->format_val = 0; @@ -1977,7 +1993,7 @@ static int azx_pcm_hw_params(struct snd_pcm_substream *substream, params_buffer_bytes(hw_params)); if (ret < 0) return ret; - mark_runtime_wc(chip, azx_dev, runtime, true); + mark_runtime_wc(chip, azx_dev, substream, true); return ret; } @@ -1986,7 +2002,6 @@ static int azx_pcm_hw_free(struct snd_pcm_substream *substream) struct azx_pcm *apcm = snd_pcm_substream_chip(substream); struct azx_dev *azx_dev = get_azx_dev(substream); struct azx *chip = apcm->chip; - struct snd_pcm_runtime *runtime = substream->runtime; struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; /* reset BDL address */ @@ -1999,7 +2014,7 @@ static int azx_pcm_hw_free(struct snd_pcm_substream *substream) snd_hda_codec_cleanup(apcm->codec, hinfo, substream); - mark_runtime_wc(chip, azx_dev, runtime, false); + mark_runtime_wc(chip, azx_dev, substream, false); return snd_pcm_lib_free_pages(substream); } @@ -3586,13 +3601,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 }, @@ -3610,13 +3625,12 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { /* 5 Series/3400 */ { PCI_DEVICE(0x8086, 0x3b56), .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH }, - /* SCH */ + /* Poulsbo */ { PCI_DEVICE(0x8086, 0x811b), - .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | - AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_LPIB }, /* Poulsbo */ + .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_NOPM }, + /* Oaktrail */ { PCI_DEVICE(0x8086, 0x080a), - .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | - AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_LPIB }, /* Oaktrail */ + .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_NOPM }, /* ICH */ { PCI_DEVICE(0x8086, 0x2668), .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC | 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 71ae23dd7103..5faaad219a7f 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4694,6 +4694,7 @@ static const struct snd_pci_quirk alc880_fixup_tbl[] = { SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_FIXUP_VOL_KNOB), SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_FIXUP_W810), SND_PCI_QUIRK(0x161f, 0x205d, "Medion Rim 2150", ALC880_FIXUP_MEDION_RIM), + SND_PCI_QUIRK(0x1631, 0xe011, "PB 13201056", ALC880_FIXUP_6ST), SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_FIXUP_F1734), SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FIXUP_FUJITSU), SND_PCI_QUIRK(0x1734, 0x10ac, "FSC AMILO Xi 1526", ALC880_FIXUP_F1734), @@ -5708,6 +5709,7 @@ static const struct alc_model_fixup alc268_fixup_models[] = { }; static const struct snd_pci_quirk alc268_fixup_tbl[] = { + SND_PCI_QUIRK(0x1025, 0x015b, "Acer AOA 150 (ZG5)", ALC268_FIXUP_INV_DMIC), /* below is codec SSID since multiple Toshiba laptops have the * same PCI SSID 1179:ff00 */ @@ -5817,6 +5819,9 @@ enum { ALC269_TYPE_ALC269VB, ALC269_TYPE_ALC269VC, ALC269_TYPE_ALC269VD, + ALC269_TYPE_ALC280, + ALC269_TYPE_ALC282, + ALC269_TYPE_ALC284, }; /* @@ -5833,10 +5838,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: @@ -6245,6 +6253,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { 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), @@ -6259,6 +6268,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), @@ -6400,7 +6410,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: @@ -6425,6 +6436,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 */ @@ -7129,6 +7154,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..ef62c435848e 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); @@ -691,7 +685,7 @@ static int arizona_hw_params(struct snd_pcm_substream *substream, } sr_val = i; - lrclk = snd_soc_params_to_bclk(params) / params_rate(params); + lrclk = rates[bclk] / params_rate(params); arizona_aif_dbg(dai, "BCLK %dHz LRCLK %dHz\n", rates[bclk], rates[bclk] / lrclk); @@ -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); @@ -1087,6 +1082,9 @@ int arizona_init_fll(struct arizona *arizona, int id, int base, int lock_irq, id, ret); } + regmap_update_bits(arizona->regmap, fll->base + 1, + ARIZONA_FLL1_FREERUN, 0); + return 0; } EXPORT_SYMBOL_GPL(arizona_init_fll); 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..d8c65f574658 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c @@ -1019,8 +1019,6 @@ static const char *wm2200_mixer_texts[] = { "EQR", "LHPF1", "LHPF2", - "LHPF3", - "LHPF4", "DSP1.1", "DSP1.2", "DSP1.3", @@ -1053,7 +1051,6 @@ static int wm2200_mixer_values[] = { 0x25, 0x50, /* EQ */ 0x51, - 0x52, 0x60, /* LHPF1 */ 0x61, /* LHPF2 */ 0x68, /* DSP1 */ @@ -1566,15 +1563,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 +1617,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 808608a053c2..988e817dca05 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); @@ -852,8 +896,7 @@ static const unsigned int wm5102_aec_loopback_values[] = { static const struct soc_enum wm5102_aec_loopback = SOC_VALUE_ENUM_SINGLE(ARIZONA_DAC_AEC_CONTROL_1, - ARIZONA_AEC_LOOPBACK_SRC_SHIFT, - ARIZONA_AEC_LOOPBACK_SRC_MASK, + ARIZONA_AEC_LOOPBACK_SRC_SHIFT, 0xf, ARRAY_SIZE(wm5102_aec_loopback_texts), wm5102_aec_loopback_texts, wm5102_aec_loopback_values); @@ -1034,10 +1077,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/wm5110.c b/sound/soc/codecs/wm5110.c index c1d46d608e5d..0320a32670d3 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -344,8 +344,7 @@ static const unsigned int wm5110_aec_loopback_values[] = { static const struct soc_enum wm5110_aec_loopback = SOC_VALUE_ENUM_SINGLE(ARIZONA_DAC_AEC_CONTROL_1, - ARIZONA_AEC_LOOPBACK_SRC_SHIFT, - ARIZONA_AEC_LOOPBACK_SRC_MASK, + ARIZONA_AEC_LOOPBACK_SRC_SHIFT, 0xf, ARRAY_SIZE(wm5110_aec_loopback_texts), wm5110_aec_loopback_texts, wm5110_aec_loopback_values); diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index ffc89fab96fb..b6b654837585 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 | GFP_DMA); + 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) @@ -384,7 +396,7 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp) hdr = (void*)&firmware->data[0]; if (memcmp(hdr->magic, "WMDR", 4) != 0) { adsp_err(dsp, "%s: invalid magic\n", file); - return -EINVAL; + goto out_fw; } adsp_dbg(dsp, "%s: v%d.%d.%d\n", file, @@ -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 | GFP_DMA); + 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/fsl/imx-pcm-dma.c b/sound/soc/fsl/imx-pcm-dma.c index bf363d8d044a..500f8ce55d78 100644 --- a/sound/soc/fsl/imx-pcm-dma.c +++ b/sound/soc/fsl/imx-pcm-dma.c @@ -154,26 +154,7 @@ static struct snd_soc_platform_driver imx_soc_platform_mx2 = { .pcm_free = imx_pcm_free, }; -static int imx_soc_platform_probe(struct platform_device *pdev) +int imx_pcm_dma_init(struct platform_device *pdev) { return snd_soc_register_platform(&pdev->dev, &imx_soc_platform_mx2); } - -static int imx_soc_platform_remove(struct platform_device *pdev) -{ - snd_soc_unregister_platform(&pdev->dev); - return 0; -} - -static struct platform_driver imx_pcm_driver = { - .driver = { - .name = "imx-pcm-audio", - .owner = THIS_MODULE, - }, - .probe = imx_soc_platform_probe, - .remove = imx_soc_platform_remove, -}; - -module_platform_driver(imx_pcm_driver); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:imx-pcm-audio"); diff --git a/sound/soc/fsl/imx-pcm-fiq.c b/sound/soc/fsl/imx-pcm-fiq.c index 5ec362ae4d01..920f945cb2f4 100644 --- a/sound/soc/fsl/imx-pcm-fiq.c +++ b/sound/soc/fsl/imx-pcm-fiq.c @@ -281,7 +281,7 @@ static struct snd_soc_platform_driver imx_soc_platform_fiq = { .pcm_free = imx_pcm_fiq_free, }; -static int imx_soc_platform_probe(struct platform_device *pdev) +int imx_pcm_fiq_init(struct platform_device *pdev) { struct imx_ssi *ssi = platform_get_drvdata(pdev); int ret; @@ -314,23 +314,3 @@ failed_register: return ret; } - -static int imx_soc_platform_remove(struct platform_device *pdev) -{ - snd_soc_unregister_platform(&pdev->dev); - return 0; -} - -static struct platform_driver imx_pcm_driver = { - .driver = { - .name = "imx-fiq-pcm-audio", - .owner = THIS_MODULE, - }, - - .probe = imx_soc_platform_probe, - .remove = imx_soc_platform_remove, -}; - -module_platform_driver(imx_pcm_driver); - -MODULE_LICENSE("GPL"); diff --git a/sound/soc/fsl/imx-pcm.c b/sound/soc/fsl/imx-pcm.c index d5cd9eff3b48..0d0625bfcb65 100644 --- a/sound/soc/fsl/imx-pcm.c +++ b/sound/soc/fsl/imx-pcm.c @@ -104,6 +104,38 @@ void imx_pcm_free(struct snd_pcm *pcm) } EXPORT_SYMBOL_GPL(imx_pcm_free); +static int imx_pcm_probe(struct platform_device *pdev) +{ + if (strcmp(pdev->id_entry->name, "imx-fiq-pcm-audio") == 0) + return imx_pcm_fiq_init(pdev); + + return imx_pcm_dma_init(pdev); +} + +static int imx_pcm_remove(struct platform_device *pdev) +{ + snd_soc_unregister_platform(&pdev->dev); + return 0; +} + +static struct platform_device_id imx_pcm_devtype[] = { + { .name = "imx-pcm-audio", }, + { .name = "imx-fiq-pcm-audio", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(platform, imx_pcm_devtype); + +static struct platform_driver imx_pcm_driver = { + .driver = { + .name = "imx-pcm", + .owner = THIS_MODULE, + }, + .id_table = imx_pcm_devtype, + .probe = imx_pcm_probe, + .remove = imx_pcm_remove, +}; +module_platform_driver(imx_pcm_driver); + MODULE_DESCRIPTION("Freescale i.MX PCM driver"); MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); MODULE_LICENSE("GPL"); diff --git a/sound/soc/fsl/imx-pcm.h b/sound/soc/fsl/imx-pcm.h index 83c0ed7d55c9..5ae13a13a353 100644 --- a/sound/soc/fsl/imx-pcm.h +++ b/sound/soc/fsl/imx-pcm.h @@ -30,4 +30,22 @@ int snd_imx_pcm_mmap(struct snd_pcm_substream *substream, int imx_pcm_new(struct snd_soc_pcm_runtime *rtd); void imx_pcm_free(struct snd_pcm *pcm); +#ifdef CONFIG_SND_SOC_IMX_PCM_DMA +int imx_pcm_dma_init(struct platform_device *pdev); +#else +static inline int imx_pcm_dma_init(struct platform_device *pdev) +{ + return -ENODEV; +} +#endif + +#ifdef CONFIG_SND_SOC_IMX_PCM_FIQ +int imx_pcm_fiq_init(struct platform_device *pdev); +#else +static inline int imx_pcm_fiq_init(struct platform_device *pdev) +{ + return -ENODEV; +} +#endif + #endif /* _IMX_PCM_H */ 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-dapm.c b/sound/soc/soc-dapm.c index 1e36bc81e5af..258acadb9e7d 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -1023,7 +1023,7 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w, if (SND_SOC_DAPM_EVENT_ON(event)) { if (w->invert & SND_SOC_DAPM_REGULATOR_BYPASS) { - ret = regulator_allow_bypass(w->regulator, true); + ret = regulator_allow_bypass(w->regulator, false); if (ret != 0) dev_warn(w->dapm->dev, "ASoC: Failed to bypass %s: %d\n", @@ -1033,7 +1033,7 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w, return regulator_enable(w->regulator); } else { if (w->invert & SND_SOC_DAPM_REGULATOR_BYPASS) { - ret = regulator_allow_bypass(w->regulator, false); + ret = regulator_allow_bypass(w->regulator, true); if (ret != 0) dev_warn(w->dapm->dev, "ASoC: Failed to unbypass %s: %d\n", @@ -3039,6 +3039,14 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, w->name, ret); return NULL; } + + if (w->invert & SND_SOC_DAPM_REGULATOR_BYPASS) { + ret = regulator_allow_bypass(w->regulator, true); + if (ret != 0) + dev_warn(w->dapm->dev, + "ASoC: Failed to unbypass %s: %d\n", + w->name, ret); + } break; case snd_soc_dapm_clock_supply: #ifdef CONFIG_CLKDEV_LOOKUP 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/mixer.c b/sound/usb/mixer.c index ed4d89c8b52a..e90daf8cdaa8 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -1331,16 +1331,23 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void } channels = (hdr->bLength - 7) / csize - 1; bmaControls = hdr->bmaControls; + if (hdr->bLength < 7 + csize) { + snd_printk(KERN_ERR "usbaudio: unit %u: " + "invalid UAC_FEATURE_UNIT descriptor\n", + unitid); + return -EINVAL; + } } else { struct uac2_feature_unit_descriptor *ftr = _ftr; csize = 4; channels = (hdr->bLength - 6) / 4 - 1; bmaControls = ftr->bmaControls; - } - - if (hdr->bLength < 7 || !csize || hdr->bLength < 7 + csize) { - snd_printk(KERN_ERR "usbaudio: unit %u: invalid UAC_FEATURE_UNIT descriptor\n", unitid); - return -EINVAL; + if (hdr->bLength < 6 + csize) { + snd_printk(KERN_ERR "usbaudio: unit %u: " + "invalid UAC_FEATURE_UNIT descriptor\n", + unitid); + return -EINVAL; + } } /* parse the source unit */ 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 c6593101c049..d82e378d37cb 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -511,6 +511,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 78e845ec65da..64d25a7a4d59 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -2289,7 +2289,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .rate_table = (unsigned int[]) { 44100, 48000, 88200, 96000 }, - .clock = 0x81, + .clock = 0x80, } }, /* Capture */ @@ -2315,7 +2315,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .rate_table = (unsigned int[]) { 44100, 48000, 88200, 96000 }, - .clock = 0x81, + .clock = 0x80, } }, /* MIDI */ diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index acc12f004c23..2c971858d6b7 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -387,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"); @@ -859,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, |