diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-10 22:13:25 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-10 22:13:25 -0400 |
commit | a2ce35273c2f1aa0dcddd8822681d64ee5f31852 (patch) | |
tree | fac2b4d526b6ca6657ea7c1b0a25efe76a3a0b5e /sound/soc/fsl/fsl_ssi.c | |
parent | bf65dea87e87c53ba4f97c6432761498bc977efd (diff) | |
parent | fd1a2a90d08b0052fa52bd36cebd0592c9e537c2 (diff) | |
download | linux-rt-a2ce35273c2f1aa0dcddd8822681d64ee5f31852.tar.gz |
Merge tag 'sound-3.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates from Takashi Iwai:
"This time it's a relatively calm update batch, but the amount isn't
too small in the end. Here we go over some highlights:
ALSA core:
- One major change is the support of nonatomic PCM operations. This
allows the trigger and other callbacks to call schedule(), which
would be useful for mailbox type communications. Already some
drivers (Digigram ones) have been converted to use together with
threaded irqs as an example.
- Improvement / fixes of DSD PCM format support
HD-audio:
- Large volume of rewrites are found in Realtek codec driver for
converting Dell and HP quirks to generic forms.
- Inverted dmic code cleanup from David.
- Realtek COEF access has been optimized.
- Now HD-audio jack infrastructure allows multiple callbacks, which
fixes / simplifies the jack-dependent power controls on STAC/IDT
and VIA codecs.
- Many additional device-specific fixups as usual
- A few deadcode cleanups, CA0132 code cleanup, etc.
ASoC:
- More componentization work from Lars-Peter, this time mainly
cleaning up the suspend and bias level transition callbacks.
- Real system support for the Intel drivers and a bunch of fixes and
enhancements for the associated CODEC drivers, this is going to
need a lot quirks over time due to the lack of any firmware
description of the boards.
- Jack detect support for simple card from Dylan Reid.
- A bunch of small fixes and enhancements for the Freescale drivers.
- New drivers for Analog Devices SSM4567, Cirrus Logic CS35L32,
Everest Semiconductor ES8328 and Freescale cards using the ASRC in
newer i.MX processors.
- A few simple-card fixes, mostly cleanups but also a fix for
interaction between GPIO 0 and simple-card.
Misc:
- Virtuoso / Oxygen updates by Clemens
- USB-audio: Yamaha MOTIF XF MIDI port name fixes
- Conversion of kernel messages to standard dev_*() in ctxfi driver"
* tag 'sound-3.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (251 commits)
ASoC: mc13783: Ensure we only try to dereference valid of_nodes
ASoC: rockchip-i2s: fix infinite loop in rockchip_snd_txctrl
ALSA: hda - Add dock port support to Thinkpad L440 (71aa:501e)
ALSA: Allow pass NULL dev for snd_pci_quirk_lookup()
ASoC: imx-es8328: Fix of_node_put() call with uninitialized object
ASoC: soc-pcm: fix sig_bits determination in soc_pcm_apply_msb()
ASoC: simple-card: Initialize headphone and mic GPIO numbers
ASoC: imx-es8328: Fix missing return code in imx_es8328_probe()
ALSA: hda - Add dock support for Thinkpad T440 (17aa:2212)
ALSA: usb: caiaq: check for cdev->n_streams > 1
ASoC: 88pm860x-codec: Fix possibly missing string termination
ASoC: core: fix use after free in snd_soc_remove_platform()
ASoC: soc-dapm: fix use after free
ALSA: hda - Make the inv dmic handling for Realtek use generic parser
ALSA: hda - Add Inverted Internal mic for Samsung Ativ book 9 (NP900X3G)
ALSA: hda - Add inverted internal mic for Asus Aspire 4830T
ASoC: Intel: byt-rt5640: fix coccinelle warnings
ASoC: fsl_esai doc: Add "fsl,vf610-esai" as compatible string
ASoC: da732x: Remove unnecessary KERN_ERR in pr_err()
ASoC: simple-card: Fix detect gpio documentation.
...
Diffstat (limited to 'sound/soc/fsl/fsl_ssi.c')
-rw-r--r-- | sound/soc/fsl/fsl_ssi.c | 89 |
1 files changed, 73 insertions, 16 deletions
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index de6ab06f58a5..e6955170dc42 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -169,6 +169,7 @@ struct fsl_ssi_private { u8 i2s_mode; bool use_dma; bool use_dual_fifo; + bool has_ipg_clk_name; unsigned int fifo_depth; struct fsl_ssi_rxtx_reg_val rxtx_reg_val; @@ -259,6 +260,11 @@ static bool fsl_ssi_is_i2s_master(struct fsl_ssi_private *ssi_private) SND_SOC_DAIFMT_CBS_CFS; } +static bool fsl_ssi_is_i2s_cbm_cfs(struct fsl_ssi_private *ssi_private) +{ + return (ssi_private->dai_fmt & SND_SOC_DAIFMT_MASTER_MASK) == + SND_SOC_DAIFMT_CBM_CFS; +} /** * fsl_ssi_isr: SSI interrupt handler * @@ -525,6 +531,11 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai); + int ret; + + ret = clk_prepare_enable(ssi_private->clk); + if (ret) + return ret; /* When using dual fifo mode, it is safer to ensure an even period * size. If appearing to an odd number while DMA always starts its @@ -539,6 +550,21 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, } /** + * fsl_ssi_shutdown: shutdown the SSI + * + */ +static void fsl_ssi_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct fsl_ssi_private *ssi_private = + snd_soc_dai_get_drvdata(rtd->cpu_dai); + + clk_disable_unprepare(ssi_private->clk); + +} + +/** * fsl_ssi_set_bclk - configure Digital Audio Interface bit clock * * Note: This function can be only called when using SSI as DAI master @@ -705,6 +731,23 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream, } } + if (!fsl_ssi_is_ac97(ssi_private)) { + u8 i2smode; + /* + * Switch to normal net mode in order to have a frame sync + * signal every 32 bits instead of 16 bits + */ + if (fsl_ssi_is_i2s_cbm_cfs(ssi_private) && sample_size == 16) + i2smode = CCSR_SSI_SCR_I2S_MODE_NORMAL | + CCSR_SSI_SCR_NET; + else + i2smode = ssi_private->i2s_mode; + + regmap_update_bits(regs, CCSR_SSI_SCR, + CCSR_SSI_SCR_NET | CCSR_SSI_SCR_I2S_MODE_MASK, + channels == 1 ? 0 : i2smode); + } + /* * FIXME: The documentation says that SxCCR[WL] should not be * modified while the SSI is enabled. The only time this can @@ -724,11 +767,6 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream, regmap_update_bits(regs, CCSR_SSI_SRCCR, CCSR_SSI_SxCCR_WL_MASK, wl); - if (!fsl_ssi_is_ac97(ssi_private)) - regmap_update_bits(regs, CCSR_SSI_SCR, - CCSR_SSI_SCR_NET | CCSR_SSI_SCR_I2S_MODE_MASK, - channels == 1 ? 0 : ssi_private->i2s_mode); - return 0; } @@ -781,6 +819,7 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev, switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFS: case SND_SOC_DAIFMT_CBS_CFS: ssi_private->i2s_mode |= CCSR_SSI_SCR_I2S_MODE_MASTER; regmap_update_bits(regs, CCSR_SSI_STCCR, @@ -854,6 +893,11 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev, case SND_SOC_DAIFMT_CBM_CFM: scr &= ~CCSR_SSI_SCR_SYS_CLK_EN; break; + case SND_SOC_DAIFMT_CBM_CFS: + strcr &= ~CCSR_SSI_STCR_TXDIR; + strcr |= CCSR_SSI_STCR_TFDIR; + scr &= ~CCSR_SSI_SCR_SYS_CLK_EN; + break; default: return -EINVAL; } @@ -1021,6 +1065,7 @@ static int fsl_ssi_dai_probe(struct snd_soc_dai *dai) static const struct snd_soc_dai_ops fsl_ssi_dai_ops = { .startup = fsl_ssi_startup, + .shutdown = fsl_ssi_shutdown, .hw_params = fsl_ssi_hw_params, .hw_free = fsl_ssi_hw_free, .set_fmt = fsl_ssi_set_dai_fmt, @@ -1146,17 +1191,22 @@ static int fsl_ssi_imx_probe(struct platform_device *pdev, u32 dmas[4]; int ret; - ssi_private->clk = devm_clk_get(&pdev->dev, NULL); + if (ssi_private->has_ipg_clk_name) + ssi_private->clk = devm_clk_get(&pdev->dev, "ipg"); + else + ssi_private->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(ssi_private->clk)) { ret = PTR_ERR(ssi_private->clk); dev_err(&pdev->dev, "could not get clock: %d\n", ret); return ret; } - ret = clk_prepare_enable(ssi_private->clk); - if (ret) { - dev_err(&pdev->dev, "clk_prepare_enable failed: %d\n", ret); - return ret; + if (!ssi_private->has_ipg_clk_name) { + ret = clk_prepare_enable(ssi_private->clk); + if (ret) { + dev_err(&pdev->dev, "clk_prepare_enable failed: %d\n", ret); + return ret; + } } /* For those SLAVE implementations, we ingore non-baudclk cases @@ -1214,8 +1264,9 @@ static int fsl_ssi_imx_probe(struct platform_device *pdev, return 0; error_pcm: - clk_disable_unprepare(ssi_private->clk); + if (!ssi_private->has_ipg_clk_name) + clk_disable_unprepare(ssi_private->clk); return ret; } @@ -1224,7 +1275,8 @@ static void fsl_ssi_imx_clean(struct platform_device *pdev, { if (!ssi_private->use_dma) imx_pcm_fiq_exit(pdev); - clk_disable_unprepare(ssi_private->clk); + if (!ssi_private->has_ipg_clk_name) + clk_disable_unprepare(ssi_private->clk); } static int fsl_ssi_probe(struct platform_device *pdev) @@ -1263,9 +1315,6 @@ static int fsl_ssi_probe(struct platform_device *pdev) if (sprop) { if (!strcmp(sprop, "ac97-slave")) ssi_private->dai_fmt = SND_SOC_DAIFMT_AC97; - else if (!strcmp(sprop, "i2s-slave")) - ssi_private->dai_fmt = SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_CBM_CFM; } ssi_private->use_dma = !of_property_read_bool(np, @@ -1299,8 +1348,16 @@ static int fsl_ssi_probe(struct platform_device *pdev) return -ENOMEM; } - ssi_private->regs = devm_regmap_init_mmio(&pdev->dev, iomem, + ret = of_property_match_string(np, "clock-names", "ipg"); + if (ret < 0) { + ssi_private->has_ipg_clk_name = false; + ssi_private->regs = devm_regmap_init_mmio(&pdev->dev, iomem, &fsl_ssi_regconfig); + } else { + ssi_private->has_ipg_clk_name = true; + ssi_private->regs = devm_regmap_init_mmio_clk(&pdev->dev, + "ipg", iomem, &fsl_ssi_regconfig); + } if (IS_ERR(ssi_private->regs)) { dev_err(&pdev->dev, "Failed to init register map\n"); return PTR_ERR(ssi_private->regs); |