aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/imx/imx-si4763.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/imx/imx-si4763.c')
-rw-r--r--sound/soc/imx/imx-si4763.c198
1 files changed, 198 insertions, 0 deletions
diff --git a/sound/soc/imx/imx-si4763.c b/sound/soc/imx/imx-si4763.c
new file mode 100644
index 00000000..7b2458ed
--- /dev/null
+++ b/sound/soc/imx/imx-si4763.c
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2008-2013 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/fsl_devices.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dai.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <mach/audmux.h>
+#include <mach/ssi.h>
+
+#include "imx-ssi.h"
+
+static struct imx_si4763_priv {
+ int sysclk;
+ int hw;
+ int active;
+ struct platform_device *pdev;
+} card_priv;
+
+static int imx_audmux_config(int slave, int master)
+{
+ unsigned int ptcr, pdcr;
+ slave = slave - 1;
+ master = master - 1;
+
+ ptcr = MXC_AUDMUX_V2_PTCR_SYN |
+ MXC_AUDMUX_V2_PTCR_TFSDIR |
+ MXC_AUDMUX_V2_PTCR_TFSEL(slave) |
+ MXC_AUDMUX_V2_PTCR_TCLKDIR |
+ MXC_AUDMUX_V2_PTCR_TCSEL(slave);
+ pdcr = MXC_AUDMUX_V2_PDCR_RXDSEL(slave);
+ mxc_audmux_v2_configure_port(master, ptcr, pdcr);
+
+ ptcr = MXC_AUDMUX_V2_PTCR_SYN;
+ pdcr = MXC_AUDMUX_V2_PDCR_RXDSEL(master);
+ mxc_audmux_v2_configure_port(slave, ptcr, pdcr);
+
+ return 0;
+}
+
+
+static int imx_3stack_si4763_startup(struct snd_pcm_substream *substream)
+{
+ struct imx_si4763_priv *priv = &card_priv;
+
+ priv->active++;
+ return 0;
+}
+
+static int imx_3stack_si4763_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ unsigned int channels = params_channels(params);
+ struct imx_ssi *ssi_mode = snd_soc_dai_get_drvdata(cpu_dai);
+ int ret = 0;
+ u32 dai_format;
+ dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS;
+
+ ssi_mode->flags |= IMX_SSI_SYN;
+
+ /* set i.MX active slot mask */
+ snd_soc_dai_set_tdm_slot(cpu_dai,
+ channels == 1 ? 0xfffffffe : 0xfffffffc,
+ channels == 1 ? 0xfffffffe : 0xfffffffc,
+ 2, 32);
+
+ /* set cpu DAI configuration */
+ ret = snd_soc_dai_set_fmt(cpu_dai, dai_format);
+ if (ret < 0)
+ return ret;
+
+ /* set the SSI system clock as input (unused) */
+ snd_soc_dai_set_sysclk(cpu_dai, IMX_SSP_SYS_CLK, 0, SND_SOC_CLOCK_IN);
+
+ snd_soc_dai_set_clkdiv(cpu_dai, IMX_SSI_TX_DIV_PM, 4);
+ snd_soc_dai_set_clkdiv(cpu_dai, IMX_SSI_TX_DIV_2, 1);
+ snd_soc_dai_set_clkdiv(cpu_dai, IMX_SSI_TX_DIV_PSR, 0);
+ return 0;
+}
+
+static void imx_3stack_si4763_shutdown(struct snd_pcm_substream *substream)
+{
+ struct imx_si4763_priv *priv = &card_priv;
+ priv->active--;
+}
+
+/*
+ * imx_3stack bt DAI opserations.
+ */
+static struct snd_soc_ops imx_3stack_si4763_ops = {
+ .startup = imx_3stack_si4763_startup,
+ .hw_params = imx_3stack_si4763_hw_params,
+ .shutdown = imx_3stack_si4763_shutdown,
+};
+
+static struct snd_soc_dai_link imx_3stack_dai = {
+ .name = "imx-si4763",
+ .stream_name = "imx-si4763",
+ .codec_dai_name = "si4763",
+ .codec_name = "si4763.0",
+ .cpu_dai_name = "imx-ssi.1",
+ .platform_name = "imx-pcm-audio.1",
+ .ops = &imx_3stack_si4763_ops,
+};
+
+static struct snd_soc_card snd_soc_card_imx_3stack = {
+ .name = "imx-audio-si4763",
+ .dai_link = &imx_3stack_dai,
+ .num_links = 1,
+};
+
+static int __devinit imx_3stack_si4763_probe(struct platform_device *pdev)
+{
+ struct mxc_audio_platform_data *plat = pdev->dev.platform_data;
+
+ card_priv.pdev = pdev;
+ card_priv.sysclk = plat->sysclk;
+ imx_audmux_config(plat->src_port, plat->ext_port);
+
+ return 0;
+
+}
+
+static int __devexit imx_3stack_si4763_remove(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static struct platform_driver imx_3stack_si4763_driver = {
+ .probe = imx_3stack_si4763_probe,
+ .remove = __devexit_p(imx_3stack_si4763_remove),
+ .driver = {
+ .name = "imx-tuner-si4763",
+ .owner = THIS_MODULE,
+ },
+};
+
+static struct platform_device *imx_3stack_snd_device;
+
+static int __init imx_3stack_asoc_init(void)
+{
+ int ret;
+ ret = platform_driver_register(&imx_3stack_si4763_driver);
+ if (ret < 0)
+ goto exit;
+
+ imx_3stack_snd_device = platform_device_alloc("soc-audio", 6);
+ if (!imx_3stack_snd_device)
+ goto err_device_alloc;
+
+ platform_set_drvdata(imx_3stack_snd_device, &snd_soc_card_imx_3stack);
+ ret = platform_device_add(imx_3stack_snd_device);
+ if (0 == ret)
+ goto exit;
+
+
+ platform_device_put(imx_3stack_snd_device);
+err_device_alloc:
+ platform_driver_unregister(&imx_3stack_si4763_driver);
+exit:
+ return ret;
+}
+
+static void __exit imx_3stack_asoc_exit(void)
+{
+ platform_driver_unregister(&imx_3stack_si4763_driver);
+ platform_device_unregister(imx_3stack_snd_device);
+}
+
+module_init(imx_3stack_asoc_init);
+module_exit(imx_3stack_asoc_exit);
+
+/* Module information */
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("ALSA SoC si4763 imx");
+MODULE_LICENSE("GPL");