diff options
author | tunik <tunik@mutagen.sam-solutions.net> | 2012-12-11 06:44:59 -0600 |
---|---|---|
committer | Justin Waters <justin.waters@timesys.com> | 2013-11-07 12:19:15 -0500 |
commit | dec87e2099a7f8ed2cc7bdd5cdc735e276aa3d1b (patch) | |
tree | e8ea8eeffd2b22602e4cb03c5ed2db6e30ce52d2 /sound | |
parent | 583f8a9b0058b6e51da0be3ca5277319bba70e35 (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/Kconfig | 5 | ||||
-rw-r--r-- | sound/soc/imx/Kconfig | 11 | ||||
-rw-r--r-- | sound/soc/imx/Makefile | 2 | ||||
-rw-r--r-- | sound/soc/imx/imx-tlv320aic3007.c | 236 |
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"); |