diff options
Diffstat (limited to 'sound/soc/imx')
-rw-r--r-- | sound/soc/imx/Kconfig | 13 | ||||
-rw-r--r-- | sound/soc/imx/Makefile | 4 | ||||
-rw-r--r-- | sound/soc/imx/imx-pcm-dma-mx2.c | 2 | ||||
-rw-r--r-- | sound/soc/imx/imx-spdif-dai.c | 137 | ||||
-rw-r--r-- | sound/soc/imx/imx-spdif.c | 144 | ||||
-rw-r--r-- | sound/soc/imx/imx-ssi.c | 3 | ||||
-rw-r--r-- | sound/soc/imx/imx-ssi.h | 6 |
7 files changed, 302 insertions, 7 deletions
diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig index feab5d38bfd..9a8a6930512 100644 --- a/sound/soc/imx/Kconfig +++ b/sound/soc/imx/Kconfig @@ -20,6 +20,9 @@ config SND_MXC_SOC_FIQ config SND_MXC_SOC_MX2 tristate +config SND_MXC_SOC_SPDIF_DAI + tristate + config SND_MXC_SOC_WM1133_EV1 tristate "Audio on the the i.MX31ADS with WM1133-EV1 fitted" depends on MACH_MX31ADS_WM1133_EV1 && EXPERIMENTAL @@ -62,4 +65,14 @@ config SND_SOC_EUKREA_TLV320 Enable I2S based access to the TLV320AIC23B codec attached to the SSI interface +config SND_SOC_IMX_SPDIF + tristate "SoC Audio support for IMX - S/PDIF" + default n + select SND_MXC_SOC_SPDIF_DAI + select SND_SOC_MXC_SPDIF + select SND_MXC_SOC_MX2 + help + Say Y if you want to add support for SoC audio on a IMX development + board with S/PDIF. + endif # SND_IMX_SOC diff --git a/sound/soc/imx/Makefile b/sound/soc/imx/Makefile index 9d9ac39c4c4..aa0097dcc9d 100644 --- a/sound/soc/imx/Makefile +++ b/sound/soc/imx/Makefile @@ -2,18 +2,22 @@ snd-soc-imx-objs := imx-ssi.o snd-soc-imx-fiq-objs := imx-pcm-fiq.o snd-soc-imx-mx2-objs := imx-pcm-dma-mx2.o +snd-soc-imx-spdif-dai-objs := imx-spdif-dai.o obj-$(CONFIG_SND_IMX_SOC) += snd-soc-imx.o obj-$(CONFIG_SND_MXC_SOC_FIQ) += snd-soc-imx-fiq.o obj-$(CONFIG_SND_MXC_SOC_MX2) += snd-soc-imx-mx2.o +obj-$(CONFIG_SND_MXC_SOC_SPDIF_DAI) += snd-soc-imx-spdif-dai.o # i.MX Machine Support snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o snd-soc-phycore-ac97-objs := phycore-ac97.o snd-soc-wm1133-ev1-objs := wm1133-ev1.o snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o +snd-soc-imx-spdif-objs := imx-spdif.o obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o obj-$(CONFIG_SND_SOC_PHYCORE_AC97) += snd-soc-phycore-ac97.o obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o obj-$(CONFIG_SND_SOC_IMX_SGTL5000) += snd-soc-imx-sgtl5000.o +obj-$(CONFIG_SND_SOC_IMX_SPDIF) += snd-soc-imx-spdif.o diff --git a/sound/soc/imx/imx-pcm-dma-mx2.c b/sound/soc/imx/imx-pcm-dma-mx2.c index c085e113fc8..c481ea5cc00 100644 --- a/sound/soc/imx/imx-pcm-dma-mx2.c +++ b/sound/soc/imx/imx-pcm-dma-mx2.c @@ -83,7 +83,7 @@ static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream, dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); - iprtd->dma_data.peripheral_type = IMX_DMATYPE_SSI_SP; + iprtd->dma_data.peripheral_type = dma_params->peripheral_type; iprtd->dma_data.priority = DMA_PRIO_HIGH; iprtd->dma_data.dma_request = dma_params->dma; diff --git a/sound/soc/imx/imx-spdif-dai.c b/sound/soc/imx/imx-spdif-dai.c new file mode 100644 index 00000000000..a3b38658c6f --- /dev/null +++ b/sound/soc/imx/imx-spdif-dai.c @@ -0,0 +1,137 @@ +/* + * ALSA SoC SPDIF Audio Layer for MXS + * + * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. + * + * Based on stmp3xxx_spdif_dai.c + * Vladimir Barinov <vbarinov@embeddedalley.com> + * Copyright 2008 SigmaTel, Inc + * Copyright 2008 Embedded Alley Solutions, Inc + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/dma-mapping.h> +#include <linux/clk.h> +#include <linux/delay.h> +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/soc.h> +#include <mach/dma.h> +#include <mach/hardware.h> + +#include "../codecs/mxc_spdif.h" + +#define MXC_SPDIF_TXFIFO_WML 0x8 +#define MXC_SPDIF_RXFIFO_WML 0x8 + +struct imx_pcm_dma_params dma_params_tx; +struct imx_pcm_dma_params dma_params_rx; + +static int imx_spdif_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *cpu_dai) +{ + /* Tx/Rx config */ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + snd_soc_dai_set_dma_data(cpu_dai, substream, &dma_params_tx); + else + snd_soc_dai_set_dma_data(cpu_dai, substream, &dma_params_rx); + + return 0; +} + +struct snd_soc_dai_ops imx_spdif_dai_ops = { + .hw_params = imx_spdif_hw_params, +}; + +struct snd_soc_dai_driver imx_spdif_dai = { + .playback = { + .channels_min = 2, + .channels_max = 2, + .rates = MXC_SPDIF_RATES_PLAYBACK, + .formats = MXC_SPDIF_FORMATS_PLAYBACK, + }, + .capture = { + .channels_min = 2, + .channels_max = 2, + .rates = MXC_SPDIF_RATES_CAPTURE, + .formats = MXC_SPDIF_FORMATS_CAPTURE, + }, + .ops = &imx_spdif_dai_ops, +}; + +static int imx_spdif_dai_probe(struct platform_device *pdev) +{ + struct resource *res; + int ret = 0; + + dma_params_tx.burstsize = MXC_SPDIF_TXFIFO_WML; + dma_params_rx.burstsize = MXC_SPDIF_RXFIFO_WML; + + dma_params_tx.peripheral_type = IMX_DMATYPE_SPDIF; + dma_params_rx.peripheral_type = IMX_DMATYPE_SPDIF; + + res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx"); + if (res) + dma_params_tx.dma = res->start; + + res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx"); + if (res) + dma_params_rx.dma = res->start; + + res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx_reg"); + if (res) + dma_params_tx.dma_addr = res->start; + + res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx_reg"); + if (res) + dma_params_rx.dma_addr = res->start; + + ret = snd_soc_register_dai(&pdev->dev, &imx_spdif_dai); + if (ret) { + dev_err(&pdev->dev, "register DAI failed\n"); + goto failed_register; + } + + return 0; + +failed_register: + return ret; +} + +static int __devexit imx_spdif_dai_remove(struct platform_device *pdev) +{ + snd_soc_unregister_dai(&pdev->dev); + return 0; +} + +static struct platform_driver imx_ssi_driver = { + .probe = imx_spdif_dai_probe, + .remove = __devexit_p(imx_spdif_dai_remove), + + .driver = { + .name = "imx-spdif-dai", + .owner = THIS_MODULE, + }, +}; + +static int __init imx_spdif_dai_init(void) +{ + return platform_driver_register(&imx_ssi_driver); +} + +static void __exit imx_spdif_dai_exit(void) +{ + platform_driver_unregister(&imx_ssi_driver); +} +module_init(imx_spdif_dai_init); +module_exit(imx_spdif_dai_exit); + +MODULE_AUTHOR("Freescale Semiconductor, Inc."); +MODULE_DESCRIPTION("IMX SPDIF DAI"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/imx/imx-spdif.c b/sound/soc/imx/imx-spdif.c new file mode 100644 index 00000000000..f336545f921 --- /dev/null +++ b/sound/soc/imx/imx-spdif.c @@ -0,0 +1,144 @@ +/* + * ASoC S/PDIF driver for IMX development boards + * + * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. + * + * based on stmp3780_devb_spdif.c + * + * Vladimir Barinov <vbarinov@embeddedalley.com> + * + * Copyright 2008 SigmaTel, Inc + * Copyright 2008 Embedded Alley Solutions, Inc + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/timer.h> +#include <linux/interrupt.h> +#include <linux/platform_device.h> +#include <linux/slab.h> + +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/soc.h> +#include <sound/soc-dapm.h> + +#include <asm/mach-types.h> +#include <asm/dma.h> +#include <mach/hardware.h> + +#include "imx-ssi.h" +#include "../codecs/mxc_spdif.h" + +/* imx digital audio interface glue - connects codec <--> CPU */ +static struct snd_soc_dai_link imx_spdif_dai_link = { + .name = "IMX SPDIF", + .stream_name = "IMX SPDIF", + .codec_dai_name = "mxc-spdif", + .codec_name = "mxc_spdif.0", + .cpu_dai_name = "imx-spdif-dai.0", + .platform_name = "imx-pcm-audio.2", /* imx-pcm-dma-mx2 */ +}; + +static struct snd_soc_card snd_soc_card_imx_spdif = { + .name = "imx-spdif", + .dai_link = &imx_spdif_dai_link, + .num_links = 1, +}; + +static int __devinit imx_spdif_audio_probe(struct platform_device *pdev) +{ + struct imx_ssi *ssi; + int ret; + + ssi = kzalloc(sizeof(*ssi), GFP_KERNEL); + if (!ssi) + return -ENOMEM; + + dev_set_drvdata(&pdev->dev, ssi); + + ssi->soc_platform_pdev = platform_device_alloc("imx-pcm-audio", 2); + if (!ssi->soc_platform_pdev) { + pr_err("%s failed platform_device_alloc\n", __func__); + return -ENOMEM; + } + + /* It may seem weird to be using struct imx_ssi here because S/PDIF + doesn't use ssi. We only use soc_platform_pdev in struct imx_ssi. + But we need it because imx-pcm-dma-mx2 initializes other fields. */ + platform_set_drvdata(ssi->soc_platform_pdev, ssi); + + ret = platform_device_add(ssi->soc_platform_pdev); + if (ret) { + dev_err(&pdev->dev, "failed to add platform device\n"); + platform_device_put(ssi->soc_platform_pdev); + return ret; + } + + return 0; +} + +static int __devexit imx_spdif_audio_remove(struct platform_device *pdev) +{ + struct imx_ssi *ssi = platform_get_drvdata(pdev); + + platform_device_unregister(ssi->soc_platform_pdev); + snd_soc_unregister_dai(&pdev->dev); + kfree(ssi); + + return 0; +} + +static struct platform_driver imx_spdif_audio_driver = { + .probe = imx_spdif_audio_probe, + .remove = __devexit_p(imx_spdif_audio_remove), + .driver = { + .name = "imx-spdif-audio-device", + .owner = THIS_MODULE, + }, +}; + +static struct platform_device *imx_spdif_snd_device; + +static int __init imx_spdif_init(void) +{ + int ret = 0; + + ret = platform_driver_register(&imx_spdif_audio_driver); + if (ret) { + pr_err("%s - failed platform_driver_register\n", __func__); + return -ENOMEM; + } + + imx_spdif_snd_device = platform_device_alloc("soc-audio", 1); + if (!imx_spdif_snd_device) { + pr_err("%s - failed platform_device_alloc\n", __func__); + return -ENOMEM; + } + + platform_set_drvdata(imx_spdif_snd_device, &snd_soc_card_imx_spdif); + + ret = platform_device_add(imx_spdif_snd_device); + if (ret) { + pr_err("ASoC S/PDIF: Platform device allocation failed\n"); + platform_device_put(imx_spdif_snd_device); + } + + return ret; +} + +static void __exit imx_spdif_exit(void) +{ + platform_driver_unregister(&imx_spdif_audio_driver); + platform_device_unregister(imx_spdif_snd_device); +} + +module_init(imx_spdif_init); +module_exit(imx_spdif_exit); + +MODULE_AUTHOR("Freescale Semiconductor, Inc."); +MODULE_DESCRIPTION("IMX EVK development board ASoC driver"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/imx/imx-ssi.c b/sound/soc/imx/imx-ssi.c index 30894ea7f33..44edf295154 100644 --- a/sound/soc/imx/imx-ssi.c +++ b/sound/soc/imx/imx-ssi.c @@ -656,6 +656,9 @@ static int imx_ssi_probe(struct platform_device *pdev) ssi->dma_params_rx.dma_addr = res->start + SSI_SRX0; ssi->dma_params_tx.dma_addr = res->start + SSI_STX0; + ssi->dma_params_tx.peripheral_type = IMX_DMATYPE_SSI_SP; + ssi->dma_params_rx.peripheral_type = IMX_DMATYPE_SSI_SP; + res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx0"); if (res) ssi->dma_params_tx.dma = res->start; diff --git a/sound/soc/imx/imx-ssi.h b/sound/soc/imx/imx-ssi.h index dc8a87530e3..1b43c620c73 100644 --- a/sound/soc/imx/imx-ssi.h +++ b/sound/soc/imx/imx-ssi.h @@ -188,12 +188,6 @@ #include <linux/dmaengine.h> #include <mach/dma.h> -struct imx_pcm_dma_params { - int dma; - unsigned long dma_addr; - int burstsize; -}; - struct imx_ssi { struct platform_device *ac97_dev; |