summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authortunik <tunik@mutagen.sam-solutions.net>2012-12-11 06:44:59 -0600
committerJustin Waters <justin.waters@timesys.com>2013-11-07 12:19:15 -0500
commitdec87e2099a7f8ed2cc7bdd5cdc735e276aa3d1b (patch)
treee8ea8eeffd2b22602e4cb03c5ed2db6e30ce52d2 /sound
parent583f8a9b0058b6e51da0be3ca5277319bba70e35 (diff)
tlv320aic3007 support
Conflicts: sound/soc/imx/Kconfig Signed-off-by: Christian Hemp <c.hemp@phytec.de>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/codecs/Kconfig5
-rw-r--r--sound/soc/imx/Kconfig11
-rw-r--r--sound/soc/imx/Makefile2
-rw-r--r--sound/soc/imx/imx-tlv320aic3007.c236
4 files changed, 253 insertions, 1 deletions
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index af1c3a9444ca..803804b91af9 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -8,6 +8,11 @@ config SND_SOC_I2C_AND_SPI
default y if I2C=y
default y if SPI_MASTER=y
+config SND_SOC_PHYTEC_CODECS
+ tristate "Build PHYTEC ASoC CODEC drivers"
+ select SND_SOC_TLV320AIC3X
+ default y
+
config SND_SOC_ALL_CODECS
tristate "Build all ASoC CODEC drivers"
select SND_SOC_88PM860X if MFD_88PM860X
diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig
index e30ebbe7e131..2e57c7d80969 100644
--- a/sound/soc/imx/Kconfig
+++ b/sound/soc/imx/Kconfig
@@ -43,7 +43,7 @@ config SND_SOC_MX27VIS_AIC32X4
config SND_SOC_PHYCORE_AC97
tristate "SoC Audio support for Phytec phyCORE (and phyCARD) boards"
- depends on MACH_PCM043 || MACH_PCA100
+ depends on MACH_PCM043 || MACH_PCA100 || MACH_MX6Q_PHYCARD
select SND_SOC_WM9712
select SND_MXC_SOC_FIQ
help
@@ -130,4 +130,13 @@ config SND_MXC_SOC_IRAM
help
Say Y if you don't want Audio playback buffers in external ram
+config SND_SOC_IMX_TLV320AIC3007
+ tristate "SoC Audio support for i.MX boards with tlv320aic3007"
+ depends on I2C && (MACH_MX6Q_PHYFLEX || MACH_MX6Q_PHYCARD)
+ select SND_SOC_TLV320AIC3X
+ select SND_MXC_SOC_MX2
+ help
+ Say Y if you want to add support for SoC audio on an i.MX board with
+ a tlv320aic3007 codec.
+
endif # SND_IMX_SOC
diff --git a/sound/soc/imx/Makefile b/sound/soc/imx/Makefile
index cc0a7d997609..99de2c10f6d1 100644
--- a/sound/soc/imx/Makefile
+++ b/sound/soc/imx/Makefile
@@ -17,6 +17,7 @@ snd-soc-wm1133-ev1-objs := wm1133-ev1.o
snd-soc-imx-wm8958-objs := imx-wm8958.o
snd-soc-imx-wm8962-objs := imx-wm8962.o
snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o
+snd-soc-imx-tlv320aic3007-objs := imx-tlv320aic3007.o
snd-soc-imx-cs42888-objs := imx-cs42888.o
snd-soc-imx-spdif-objs := imx-spdif.o
snd-soc-imx-si4763-objs := imx-si4763.o
@@ -29,6 +30,7 @@ obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o
obj-$(CONFIG_SND_SOC_IMX_WM8958) += snd-soc-imx-wm8958.o
obj-$(CONFIG_SND_SOC_IMX_WM8962) += snd-soc-imx-wm8962.o
obj-$(CONFIG_SND_SOC_IMX_SGTL5000) += snd-soc-imx-sgtl5000.o
+obj-$(CONFIG_SND_SOC_IMX_TLV320AIC3007) += snd-soc-imx-tlv320aic3007.o
obj-$(CONFIG_SND_SOC_IMX_CS42888) += snd-soc-imx-cs42888.o
obj-$(CONFIG_SND_SOC_IMX_SPDIF) += snd-soc-imx-spdif.o
obj-$(CONFIG_SND_SOC_IMX_HDMI) += snd-soc-imx-hdmi.o
diff --git a/sound/soc/imx/imx-tlv320aic3007.c b/sound/soc/imx/imx-tlv320aic3007.c
new file mode 100644
index 000000000000..44a7eaa6ef15
--- /dev/null
+++ b/sound/soc/imx/imx-tlv320aic3007.c
@@ -0,0 +1,236 @@
+/*
+ * ASoC driver for i.MX6 boards with tlv320aic3007 codec
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/fsl_devices.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <asm/mach-types.h>
+#include <mach/audmux.h>
+
+#include "../codecs/tlv320aic3x.h"
+#include "imx-ssi.h"
+
+#define CODEC_CLOCK 19200000
+
+static int imx_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 *codec_dai = rtd->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ int ret;
+ unsigned int channels = params_channels(params);
+
+ // set codec DAI configuration
+ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM);
+ if (ret < 0)
+ return ret;
+
+ /* set cpu DAI configuration */
+ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_dai_set_sysclk(codec_dai, 0, CODEC_CLOCK, SND_SOC_CLOCK_OUT);
+ if (ret < 0)
+ return ret;
+
+ snd_soc_dai_set_tdm_slot(cpu_dai, 0xfffffffc, 0xfffffffc, 2, 0);
+
+ ret = snd_soc_dai_set_sysclk(cpu_dai, IMX_SSP_SYS_CLK, 0,
+ SND_SOC_CLOCK_IN);
+
+ return 0;
+}
+
+static struct snd_soc_ops imx_ops = {
+ .hw_params = imx_hw_params,
+};
+
+/* davinci-evm machine dapm widgets */
+static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
+ SND_SOC_DAPM_HP("Headphone Jack", NULL),
+ SND_SOC_DAPM_LINE("Line Out", NULL),
+ SND_SOC_DAPM_MIC("Mic Jack", NULL),
+ SND_SOC_DAPM_LINE("Line In", NULL),
+};
+
+/* davinci-evm machine audio_mapnections to the codec pins */
+static const struct snd_soc_dapm_route audio_map[] = {
+ /* Headphone connected to HPLOUT, HPROUT */
+ {"Headphone Jack", NULL, "HPLOUT"},
+ {"Headphone Jack", NULL, "HPROUT"},
+
+ /* Line Out connected to LLOUT, RLOUT */
+ {"Line Out", NULL, "LLOUT"},
+ {"Line Out", NULL, "RLOUT"},
+
+ /* Mic connected to (MIC3L | MIC3R) */
+ {"MIC3L", NULL, "Mic Bias 2V"},
+ {"MIC3R", NULL, "Mic Bias 2V"},
+ {"Mic Bias 2V", NULL, "Mic Jack"},
+
+ /* Line In connected to (LINE1L | LINE2L), (LINE1R | LINE2R) */
+ {"LINE1L", NULL, "Line In"},
+ {"LINE2L", NULL, "Line In"},
+ {"LINE1R", NULL, "Line In"},
+ {"LINE2R", NULL, "Line In"},
+};
+
+
+/* Logic for a aic3x as connected on a imx */
+static int imx_aic3x_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_dapm_context *dapm = &codec->dapm;
+
+ /* Add davinci-evm specific widgets */
+ snd_soc_dapm_new_controls(dapm, aic3x_dapm_widgets,
+ ARRAY_SIZE(aic3x_dapm_widgets));
+
+ /* Set up davinci-evm specific audio path audio_map */
+ snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
+
+ /* not connected */
+ snd_soc_dapm_disable_pin(dapm, "MONO_LOUT");
+ snd_soc_dapm_disable_pin(dapm, "HPLCOM");
+ snd_soc_dapm_disable_pin(dapm, "HPRCOM");
+
+ /* always connected */
+ snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
+ snd_soc_dapm_enable_pin(dapm, "Line Out");
+ snd_soc_dapm_enable_pin(dapm, "Mic Jack");
+ snd_soc_dapm_enable_pin(dapm, "Line In");
+
+ snd_soc_dapm_sync(dapm);
+
+ return 0;
+}
+
+static struct snd_soc_dai_link imx_tlv320aic3007_dai = {
+ .name = "TLV320AIC3X",
+ .stream_name = "AIC3X",
+ .cpu_dai_name= "imx-ssi.1",
+ .codec_dai_name = "tlv320aic3x-hifi",
+ .codec_name = "tlv320aic3x-codec.1-0018",
+ .platform_name = "imx-pcm-audio.1",
+ .init = imx_aic3x_init,
+ .ops = &imx_ops,
+};
+
+
+static struct snd_soc_card imx_tlv320aic3007_card = {
+ .name = "imx_tlv320aic3007-audio",
+ .dai_link = &imx_tlv320aic3007_dai,
+ .num_links = 1,
+};
+
+
+static int imx_audmux_config(int slave, int master)
+{
+ unsigned int ptcr, pdcr;
+ unsigned int ptcr_read, pdcr_read;
+ slave = slave - 1;
+ master = master - 1;
+
+ /* SSI0 mastered by port 5 */
+ ptcr = MXC_AUDMUX_V2_PTCR_TFSDIR |
+ MXC_AUDMUX_V2_PTCR_TFSEL(master) |
+ MXC_AUDMUX_V2_PTCR_TCLKDIR |
+ MXC_AUDMUX_V2_PTCR_TCSEL(master);
+ pdcr = MXC_AUDMUX_V2_PDCR_RXDSEL(master);
+ mxc_audmux_v2_configure_port(slave, ptcr, pdcr);
+
+ ptcr = 0;
+ pdcr = MXC_AUDMUX_V2_PDCR_RXDSEL(slave);
+ mxc_audmux_v2_configure_port(master, ptcr, pdcr);
+
+ return 0;
+}
+
+
+static int __devinit imx_tlv320aic3007_probe(struct platform_device *pdev)
+{
+ struct mxc_audio_platform_data *plat = pdev->dev.platform_data;
+
+ imx_audmux_config(plat->src_port, plat->ext_port);
+
+ int ret = 0;
+
+ ret = -EINVAL;
+ if (plat->init && plat->init())
+ return ret;
+
+ return 0;
+}
+
+static int imx_tlv320aic3007_remove(struct platform_device *pdev)
+{
+ struct mxc_audio_platform_data *plat = pdev->dev.platform_data;
+
+ if (plat->finit)
+ plat->finit();
+
+ return 0;
+}
+
+
+static struct platform_driver tlv320aic3007_audio_driver = {
+ .probe = imx_tlv320aic3007_probe,
+ .remove = imx_tlv320aic3007_remove,
+ .driver = {
+ .name = "tlv320aic3007",
+ },
+};
+
+
+
+static struct platform_device *imx_tlv320aic3007_snd_device;
+
+static int __init imx_tlv320aic3007_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&tlv320aic3007_audio_driver);
+ if (ret)
+ return -ENOMEM;
+
+ imx_tlv320aic3007_snd_device = platform_device_alloc("soc-audio", -1);
+ if (!imx_tlv320aic3007_snd_device)
+ return -ENOMEM;
+
+ platform_set_drvdata(imx_tlv320aic3007_snd_device, &imx_tlv320aic3007_card);
+ ret = platform_device_add(imx_tlv320aic3007_snd_device);
+ if (ret)
+ {
+ platform_device_put(imx_tlv320aic3007_snd_device);
+ }
+
+ return ret;
+}
+
+static void __exit imx_tlv320aic3007_exit(void)
+{
+ platform_device_unregister(imx_tlv320aic3007_snd_device);
+}
+
+module_init(imx_tlv320aic3007_init);
+module_exit(imx_tlv320aic3007_exit);
+
+MODULE_AUTHOR("Lavnikevich Dmitry");
+MODULE_DESCRIPTION("TLV320AIC3007 PHYFlex ASoC driver");
+MODULE_LICENSE("GPL");