diff options
Diffstat (limited to 'sound/soc/omap')
-rw-r--r-- | sound/soc/omap/Kconfig | 35 | ||||
-rw-r--r-- | sound/soc/omap/Makefile | 8 | ||||
-rw-r--r-- | sound/soc/omap/n810.c | 10 | ||||
-rw-r--r-- | sound/soc/omap/omap-mcbsp.c | 57 | ||||
-rw-r--r-- | sound/soc/omap/omap-pcm.c | 12 | ||||
-rw-r--r-- | sound/soc/omap/omap2evm.c | 151 | ||||
-rw-r--r-- | sound/soc/omap/omap3beagle.c | 149 | ||||
-rw-r--r-- | sound/soc/omap/omap3pandora.c | 311 | ||||
-rw-r--r-- | sound/soc/omap/osk5912.c | 6 | ||||
-rw-r--r-- | sound/soc/omap/overo.c | 148 | ||||
-rw-r--r-- | sound/soc/omap/sdp3430.c | 152 |
11 files changed, 1012 insertions, 27 deletions
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig index 8b7766b998d..a7b1d77b210 100644 --- a/sound/soc/omap/Kconfig +++ b/sound/soc/omap/Kconfig @@ -1,6 +1,6 @@ config SND_OMAP_SOC tristate "SoC Audio for the Texas Instruments OMAP chips" - depends on ARCH_OMAP && SND_SOC + depends on ARCH_OMAP config SND_OMAP_SOC_MCBSP tristate @@ -21,3 +21,36 @@ config SND_OMAP_SOC_OSK5912 select SND_SOC_TLV320AIC23 help Say Y if you want to add support for SoC audio on osk5912. + +config SND_OMAP_SOC_OVERO + tristate "SoC Audio support for Gumstix Overo" + depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OVERO + select SND_OMAP_SOC_MCBSP + select SND_SOC_TWL4030 + help + Say Y if you want to add support for SoC audio on the Gumstix Overo. + +config SND_OMAP_SOC_OMAP2EVM + tristate "SoC Audio support for OMAP2EVM board" + depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP2EVM + select SND_OMAP_SOC_MCBSP + select SND_SOC_TWL4030 + help + Say Y if you want to add support for SoC audio on the omap2evm board. + +config SND_OMAP_SOC_SDP3430 + tristate "SoC Audio support for Texas Instruments SDP3430" + depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_3430SDP + select SND_OMAP_SOC_MCBSP + select SND_SOC_TWL4030 + help + Say Y if you want to add support for SoC audio on Texas Instruments + SDP3430. + +config SND_OMAP_SOC_OMAP3_PANDORA + tristate "SoC Audio support for OMAP3 Pandora" + depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP3_PANDORA + select SND_OMAP_SOC_MCBSP + select SND_SOC_TWL4030 + help + Say Y if you want to add support for SoC audio on the OMAP3 Pandora. diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile index e09d1f297f6..76fedd96e36 100644 --- a/sound/soc/omap/Makefile +++ b/sound/soc/omap/Makefile @@ -8,6 +8,14 @@ obj-$(CONFIG_SND_OMAP_SOC_MCBSP) += snd-soc-omap-mcbsp.o # OMAP Machine Support snd-soc-n810-objs := n810.o snd-soc-osk5912-objs := osk5912.o +snd-soc-overo-objs := overo.o +snd-soc-omap2evm-objs := omap2evm.o +snd-soc-sdp3430-objs := sdp3430.o +snd-soc-omap3pandora-objs := omap3pandora.o obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o +obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o +obj-$(CONFIG_MACH_OMAP2EVM) += snd-soc-omap2evm.o +obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o +obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c index fae3ad36e0b..25593fee912 100644 --- a/sound/soc/omap/n810.c +++ b/sound/soc/omap/n810.c @@ -70,9 +70,13 @@ static void n810_ext_control(struct snd_soc_codec *codec) static int n810_startup(struct snd_pcm_substream *substream) { + struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_codec *codec = rtd->socdev->codec; + snd_pcm_hw_constraint_minmax(runtime, + SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2); + n810_ext_control(codec); return clk_enable(sys_clkout2); } @@ -282,8 +286,9 @@ static struct snd_soc_dai_link n810_dai = { }; /* Audio machine driver */ -static struct snd_soc_machine snd_soc_machine_n810 = { +static struct snd_soc_card snd_soc_n810 = { .name = "N810", + .platform = &omap_soc_platform, .dai_link = &n810_dai, .num_links = 1, }; @@ -298,8 +303,7 @@ static struct aic3x_setup_data n810_aic33_setup = { /* Audio subsystem */ static struct snd_soc_device n810_snd_devdata = { - .machine = &snd_soc_machine_n810, - .platform = &omap_soc_platform, + .card = &snd_soc_n810, .codec_dev = &soc_codec_dev_aic3x, .codec_data = &n810_aic33_setup, }; diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index 8485a8a9d0f..7b86373007c 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c @@ -36,9 +36,7 @@ #include "omap-mcbsp.h" #include "omap-pcm.h" -#define OMAP_MCBSP_RATES (SNDRV_PCM_RATE_44100 | \ - SNDRV_PCM_RATE_48000 | \ - SNDRV_PCM_RATE_KNOT) +#define OMAP_MCBSP_RATES (SNDRV_PCM_RATE_8000_96000) struct omap_mcbsp_data { unsigned int bus_id; @@ -140,7 +138,8 @@ static const unsigned long omap34xx_mcbsp_port[][2] = { static const unsigned long omap34xx_mcbsp_port[][2] = {}; #endif -static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream) +static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; @@ -153,7 +152,8 @@ static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream) return err; } -static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream) +static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; @@ -165,7 +165,8 @@ static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream) } } -static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd) +static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; @@ -194,14 +195,15 @@ static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd) } static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id; - int wlen; + int wlen, channels; unsigned long port; if (cpu_class_is_omap1()) { @@ -230,12 +232,17 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, return 0; } - switch (params_channels(params)) { + channels = params_channels(params); + switch (channels) { case 2: - /* Set 1 word per (McBPSP) frame and use dual-phase frames */ - regs->rcr2 |= RFRLEN2(1 - 1) | RPHASE; + /* Use dual-phase frames */ + regs->rcr2 |= RPHASE; + regs->xcr2 |= XPHASE; + case 1: + /* Set 1 word per (McBSP) frame */ + regs->rcr2 |= RFRLEN2(1 - 1); regs->rcr1 |= RFRLEN1(1 - 1); - regs->xcr2 |= XFRLEN2(1 - 1) | XPHASE; + regs->xcr2 |= XFRLEN2(1 - 1); regs->xcr1 |= XFRLEN1(1 - 1); break; default: @@ -264,8 +271,8 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, regs->srgr1 |= FWID(wlen - 1); break; case SND_SOC_DAIFMT_DSP_A: - regs->srgr2 |= FPER(wlen * 2 - 1); - regs->srgr1 |= FWID(wlen * 2 - 2); + regs->srgr2 |= FPER(wlen * channels - 1); + regs->srgr1 |= FWID(wlen * channels - 2); break; } @@ -452,17 +459,16 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, #define OMAP_MCBSP_DAI_BUILDER(link_id) \ { \ - .name = "omap-mcbsp-dai-(link_id)", \ + .name = "omap-mcbsp-dai-"#link_id, \ .id = (link_id), \ - .type = SND_SOC_DAI_I2S, \ .playback = { \ - .channels_min = 2, \ + .channels_min = 1, \ .channels_max = 2, \ .rates = OMAP_MCBSP_RATES, \ .formats = SNDRV_PCM_FMTBIT_S16_LE, \ }, \ .capture = { \ - .channels_min = 2, \ + .channels_min = 1, \ .channels_max = 2, \ .rates = OMAP_MCBSP_RATES, \ .formats = SNDRV_PCM_FMTBIT_S16_LE, \ @@ -472,8 +478,6 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, .shutdown = omap_mcbsp_dai_shutdown, \ .trigger = omap_mcbsp_dai_trigger, \ .hw_params = omap_mcbsp_dai_hw_params, \ - }, \ - .dai_ops = { \ .set_fmt = omap_mcbsp_dai_set_dai_fmt, \ .set_clkdiv = omap_mcbsp_dai_set_clkdiv, \ .set_sysclk = omap_mcbsp_dai_set_dai_sysclk, \ @@ -495,6 +499,19 @@ struct snd_soc_dai omap_mcbsp_dai[] = { EXPORT_SYMBOL_GPL(omap_mcbsp_dai); +static int __init snd_omap_mcbsp_init(void) +{ + return snd_soc_register_dais(omap_mcbsp_dai, + ARRAY_SIZE(omap_mcbsp_dai)); +} +module_init(snd_omap_mcbsp_init); + +static void __exit snd_omap_mcbsp_exit(void) +{ + snd_soc_unregister_dais(omap_mcbsp_dai, ARRAY_SIZE(omap_mcbsp_dai)); +} +module_exit(snd_omap_mcbsp_exit); + MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@nokia.com>"); MODULE_DESCRIPTION("OMAP I2S SoC Interface"); MODULE_LICENSE("GPL"); diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c index acd68efb2b7..803581c9280 100644 --- a/sound/soc/omap/omap-pcm.c +++ b/sound/soc/omap/omap-pcm.c @@ -354,6 +354,18 @@ struct snd_soc_platform omap_soc_platform = { }; EXPORT_SYMBOL_GPL(omap_soc_platform); +static int __init omap_soc_platform_init(void) +{ + return snd_soc_register_platform(&omap_soc_platform); +} +module_init(omap_soc_platform_init); + +static void __exit omap_soc_platform_exit(void) +{ + snd_soc_unregister_platform(&omap_soc_platform); +} +module_exit(omap_soc_platform_exit); + MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@nokia.com>"); MODULE_DESCRIPTION("OMAP PCM DMA module"); MODULE_LICENSE("GPL"); diff --git a/sound/soc/omap/omap2evm.c b/sound/soc/omap/omap2evm.c new file mode 100644 index 00000000000..0c2322dcf02 --- /dev/null +++ b/sound/soc/omap/omap2evm.c @@ -0,0 +1,151 @@ +/* + * omap2evm.c -- SoC audio machine driver for omap2evm board + * + * Author: Arun KS <arunks@mistralsolutions.com> + * + * Based on sound/soc/omap/overo.c by Steve Sakoman + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include <linux/clk.h> +#include <linux/platform_device.h> +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/soc.h> +#include <sound/soc-dapm.h> + +#include <asm/mach-types.h> +#include <mach/hardware.h> +#include <mach/gpio.h> +#include <mach/mcbsp.h> + +#include "omap-mcbsp.h" +#include "omap-pcm.h" +#include "../codecs/twl4030.h" + +static int omap2evm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + int ret; + + /* 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) { + printk(KERN_ERR "can't set codec DAI configuration\n"); + 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) { + printk(KERN_ERR "can't set cpu DAI configuration\n"); + return ret; + } + + /* Set the codec system clock for DAC and ADC */ + ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000, + SND_SOC_CLOCK_IN); + if (ret < 0) { + printk(KERN_ERR "can't set codec system clock\n"); + return ret; + } + + return 0; +} + +static struct snd_soc_ops omap2evm_ops = { + .hw_params = omap2evm_hw_params, +}; + +/* Digital audio interface glue - connects codec <--> CPU */ +static struct snd_soc_dai_link omap2evm_dai = { + .name = "TWL4030", + .stream_name = "TWL4030", + .cpu_dai = &omap_mcbsp_dai[0], + .codec_dai = &twl4030_dai, + .ops = &omap2evm_ops, +}; + +/* Audio machine driver */ +static struct snd_soc_card snd_soc_omap2evm = { + .name = "omap2evm", + .platform = &omap_soc_platform, + .dai_link = &omap2evm_dai, + .num_links = 1, +}; + +/* Audio subsystem */ +static struct snd_soc_device omap2evm_snd_devdata = { + .card = &snd_soc_omap2evm, + .codec_dev = &soc_codec_dev_twl4030, +}; + +static struct platform_device *omap2evm_snd_device; + +static int __init omap2evm_soc_init(void) +{ + int ret; + + if (!machine_is_omap2evm()) { + pr_debug("Not omap2evm!\n"); + return -ENODEV; + } + printk(KERN_INFO "omap2evm SoC init\n"); + + omap2evm_snd_device = platform_device_alloc("soc-audio", -1); + if (!omap2evm_snd_device) { + printk(KERN_ERR "Platform device allocation failed\n"); + return -ENOMEM; + } + + platform_set_drvdata(omap2evm_snd_device, &omap2evm_snd_devdata); + omap2evm_snd_devdata.dev = &omap2evm_snd_device->dev; + *(unsigned int *)omap2evm_dai.cpu_dai->private_data = 1; /* McBSP2 */ + + ret = platform_device_add(omap2evm_snd_device); + if (ret) + goto err1; + + return 0; + +err1: + printk(KERN_ERR "Unable to add platform device\n"); + platform_device_put(omap2evm_snd_device); + + return ret; +} +module_init(omap2evm_soc_init); + +static void __exit omap2evm_soc_exit(void) +{ + platform_device_unregister(omap2evm_snd_device); +} +module_exit(omap2evm_soc_exit); + +MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>"); +MODULE_DESCRIPTION("ALSA SoC omap2evm"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/omap/omap3beagle.c b/sound/soc/omap/omap3beagle.c new file mode 100644 index 00000000000..fd24a4acd2f --- /dev/null +++ b/sound/soc/omap/omap3beagle.c @@ -0,0 +1,149 @@ +/* + * omap3beagle.c -- SoC audio for OMAP3 Beagle + * + * Author: Steve Sakoman <steve@sakoman.com> + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include <linux/clk.h> +#include <linux/platform_device.h> +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/soc.h> +#include <sound/soc-dapm.h> + +#include <asm/mach-types.h> +#include <mach/hardware.h> +#include <mach/gpio.h> +#include <mach/mcbsp.h> + +#include "omap-mcbsp.h" +#include "omap-pcm.h" +#include "../codecs/twl4030.h" + +static int omap3beagle_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->dai->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + int ret; + + /* 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) { + printk(KERN_ERR "can't set codec DAI configuration\n"); + 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) { + printk(KERN_ERR "can't set cpu DAI configuration\n"); + return ret; + } + + /* Set the codec system clock for DAC and ADC */ + ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000, + SND_SOC_CLOCK_IN); + if (ret < 0) { + printk(KERN_ERR "can't set codec system clock\n"); + return ret; + } + + return 0; +} + +static struct snd_soc_ops omap3beagle_ops = { + .hw_params = omap3beagle_hw_params, +}; + +/* Digital audio interface glue - connects codec <--> CPU */ +static struct snd_soc_dai_link omap3beagle_dai = { + .name = "TWL4030", + .stream_name = "TWL4030", + .cpu_dai = &omap_mcbsp_dai[0], + .codec_dai = &twl4030_dai, + .ops = &omap3beagle_ops, +}; + +/* Audio machine driver */ +static struct snd_soc_card snd_soc_omap3beagle = { + .name = "omap3beagle", + .platform = &omap_soc_platform, + .dai_link = &omap3beagle_dai, + .num_links = 1, +}; + +/* Audio subsystem */ +static struct snd_soc_device omap3beagle_snd_devdata = { + .card = &snd_soc_omap3beagle, + .codec_dev = &soc_codec_dev_twl4030, +}; + +static struct platform_device *omap3beagle_snd_device; + +static int __init omap3beagle_soc_init(void) +{ + int ret; + + if (!machine_is_omap3_beagle()) { + pr_debug("Not OMAP3 Beagle!\n"); + return -ENODEV; + } + pr_info("OMAP3 Beagle SoC init\n"); + + omap3beagle_snd_device = platform_device_alloc("soc-audio", -1); + if (!omap3beagle_snd_device) { + printk(KERN_ERR "Platform device allocation failed\n"); + return -ENOMEM; + } + + platform_set_drvdata(omap3beagle_snd_device, &omap3beagle_snd_devdata); + omap3beagle_snd_devdata.dev = &omap3beagle_snd_device->dev; + *(unsigned int *)omap3beagle_dai.cpu_dai->private_data = 1; /* McBSP2 */ + + ret = platform_device_add(omap3beagle_snd_device); + if (ret) + goto err1; + + return 0; + +err1: + printk(KERN_ERR "Unable to add platform device\n"); + platform_device_put(omap3beagle_snd_device); + + return ret; +} + +static void __exit omap3beagle_soc_exit(void) +{ + platform_device_unregister(omap3beagle_snd_device); +} + +module_init(omap3beagle_soc_init); +module_exit(omap3beagle_soc_exit); + +MODULE_AUTHOR("Steve Sakoman <steve@sakoman.com>"); +MODULE_DESCRIPTION("ALSA SoC OMAP3 Beagle"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/omap/omap3pandora.c b/sound/soc/omap/omap3pandora.c new file mode 100644 index 00000000000..bd91594496b --- /dev/null +++ b/sound/soc/omap/omap3pandora.c @@ -0,0 +1,311 @@ +/* + * omap3pandora.c -- SoC audio for Pandora Handheld Console + * + * Author: GraÅžvydas Ignotas <notasas@gmail.com> + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include <linux/clk.h> +#include <linux/platform_device.h> +#include <linux/gpio.h> +#include <linux/delay.h> + +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/soc.h> +#include <sound/soc-dapm.h> + +#include <asm/mach-types.h> + +#include "omap-mcbsp.h" +#include "omap-pcm.h" +#include "../codecs/twl4030.h" + +#define OMAP3_PANDORA_DAC_POWER_GPIO 118 +#define OMAP3_PANDORA_AMP_POWER_GPIO 14 + +#define PREFIX "ASoC omap3pandora: " + +static int omap3pandora_cmn_hw_params(struct snd_soc_dai *codec_dai, + struct snd_soc_dai *cpu_dai, unsigned int fmt) +{ + int ret; + + /* Set codec DAI configuration */ + ret = snd_soc_dai_set_fmt(codec_dai, fmt); + if (ret < 0) { + pr_err(PREFIX "can't set codec DAI configuration\n"); + return ret; + } + + /* Set cpu DAI configuration */ + ret = snd_soc_dai_set_fmt(cpu_dai, fmt); + if (ret < 0) { + pr_err(PREFIX "can't set cpu DAI configuration\n"); + return ret; + } + + /* Set the codec system clock for DAC and ADC */ + ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000, + SND_SOC_CLOCK_IN); + if (ret < 0) { + pr_err(PREFIX "can't set codec system clock\n"); + return ret; + } + + /* Set McBSP clock to external */ + ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_SYSCLK_CLKS_EXT, 0, + SND_SOC_CLOCK_IN); + if (ret < 0) { + pr_err(PREFIX "can't set cpu system clock\n"); + return ret; + } + + ret = snd_soc_dai_set_clkdiv(cpu_dai, OMAP_MCBSP_CLKGDV, 8); + if (ret < 0) { + pr_err(PREFIX "can't set SRG clock divider\n"); + return ret; + } + + return 0; +} + +static int omap3pandora_out_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->dai->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + + return omap3pandora_cmn_hw_params(codec_dai, cpu_dai, + SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_IB_NF | + SND_SOC_DAIFMT_CBS_CFS); +} + +static int omap3pandora_in_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->dai->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + + return omap3pandora_cmn_hw_params(codec_dai, cpu_dai, + SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS); +} + +static int omap3pandora_hp_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *k, int event) +{ + if (SND_SOC_DAPM_EVENT_ON(event)) { + gpio_set_value(OMAP3_PANDORA_DAC_POWER_GPIO, 1); + gpio_set_value(OMAP3_PANDORA_AMP_POWER_GPIO, 1); + } else { + gpio_set_value(OMAP3_PANDORA_AMP_POWER_GPIO, 0); + mdelay(1); + gpio_set_value(OMAP3_PANDORA_DAC_POWER_GPIO, 0); + } + + return 0; +} + +/* + * Audio paths on Pandora board: + * + * |O| ---> PCM DAC +-> AMP -> Headphone Jack + * |M| A +--------> Line Out + * |A| <~~clk~~+ + * |P| <--- TWL4030 <--------- Line In and MICs + */ +static const struct snd_soc_dapm_widget omap3pandora_out_dapm_widgets[] = { + SND_SOC_DAPM_DAC("PCM DAC", "Playback", SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_PGA_E("Headphone Amplifier", SND_SOC_NOPM, + 0, 0, NULL, 0, omap3pandora_hp_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_HP("Headphone Jack", NULL), + SND_SOC_DAPM_LINE("Line Out", NULL), +}; + +static const struct snd_soc_dapm_widget omap3pandora_in_dapm_widgets[] = { + SND_SOC_DAPM_MIC("Mic (Internal)", NULL), + SND_SOC_DAPM_MIC("Mic (external)", NULL), + SND_SOC_DAPM_LINE("Line In", NULL), +}; + +static const struct snd_soc_dapm_route omap3pandora_out_map[] = { + {"Headphone Amplifier", NULL, "PCM DAC"}, + {"Line Out", NULL, "PCM DAC"}, + {"Headphone Jack", NULL, "Headphone Amplifier"}, +}; + +static const struct snd_soc_dapm_route omap3pandora_in_map[] = { + {"INL", NULL, "Line In"}, + {"INR", NULL, "Line In"}, + {"INL", NULL, "Mic (Internal)"}, + {"INR", NULL, "Mic (external)"}, +}; + +static int omap3pandora_out_init(struct snd_soc_codec *codec) +{ + int ret; + + ret = snd_soc_dapm_new_controls(codec, omap3pandora_out_dapm_widgets, + ARRAY_SIZE(omap3pandora_out_dapm_widgets)); + if (ret < 0) + return ret; + + snd_soc_dapm_add_routes(codec, omap3pandora_out_map, + ARRAY_SIZE(omap3pandora_out_map)); + + return snd_soc_dapm_sync(codec); +} + +static int omap3pandora_in_init(struct snd_soc_codec *codec) +{ + int ret; + + ret = snd_soc_dapm_new_controls(codec, omap3pandora_in_dapm_widgets, + ARRAY_SIZE(omap3pandora_in_dapm_widgets)); + if (ret < 0) + return ret; + + snd_soc_dapm_add_routes(codec, omap3pandora_in_map, + ARRAY_SIZE(omap3pandora_in_map)); + + return snd_soc_dapm_sync(codec); +} + +static struct snd_soc_ops omap3pandora_out_ops = { + .hw_params = omap3pandora_out_hw_params, +}; + +static struct snd_soc_ops omap3pandora_in_ops = { + .hw_params = omap3pandora_in_hw_params, +}; + +/* Digital audio interface glue - connects codec <--> CPU */ +static struct snd_soc_dai_link omap3pandora_dai[] = { + { + .name = "PCM1773", + .stream_name = "HiFi Out", + .cpu_dai = &omap_mcbsp_dai[0], + .codec_dai = &twl4030_dai, + .ops = &omap3pandora_out_ops, + .init = omap3pandora_out_init, + }, { + .name = "TWL4030", + .stream_name = "Line/Mic In", + .cpu_dai = &omap_mcbsp_dai[1], + .codec_dai = &twl4030_dai, + .ops = &omap3pandora_in_ops, + .init = omap3pandora_in_init, + } +}; + +/* SoC card */ +static struct snd_soc_card snd_soc_card_omap3pandora = { + .name = "omap3pandora", + .platform = &omap_soc_platform, + .dai_link = omap3pandora_dai, + .num_links = ARRAY_SIZE(omap3pandora_dai), +}; + +/* Audio subsystem */ +static struct snd_soc_device omap3pandora_snd_data = { + .card = &snd_soc_card_omap3pandora, + .codec_dev = &soc_codec_dev_twl4030, +}; + +static struct platform_device *omap3pandora_snd_device; + +static int __init omap3pandora_soc_init(void) +{ + int ret; + + if (!machine_is_omap3_pandora()) { + pr_debug(PREFIX "Not OMAP3 Pandora\n"); + return -ENODEV; + } + pr_info("OMAP3 Pandora SoC init\n"); + + ret = gpio_request(OMAP3_PANDORA_DAC_POWER_GPIO, "dac_power"); + if (ret) { + pr_err(PREFIX "Failed to get DAC power GPIO\n"); + return ret; + } + + ret = gpio_direction_output(OMAP3_PANDORA_DAC_POWER_GPIO, 0); + if (ret) { + pr_err(PREFIX "Failed to set DAC power GPIO direction\n"); + goto fail0; + } + + ret = gpio_request(OMAP3_PANDORA_AMP_POWER_GPIO, "amp_power"); + if (ret) { + pr_err(PREFIX "Failed to get amp power GPIO\n"); + goto fail0; + } + + ret = gpio_direction_output(OMAP3_PANDORA_AMP_POWER_GPIO, 0); + if (ret) { + pr_err(PREFIX "Failed to set amp power GPIO direction\n"); + goto fail1; + } + + omap3pandora_snd_device = platform_device_alloc("soc-audio", -1); + if (omap3pandora_snd_device == NULL) { + pr_err(PREFIX "Platform device allocation failed\n"); + ret = -ENOMEM; + goto fail1; + } + + platform_set_drvdata(omap3pandora_snd_device, &omap3pandora_snd_data); + omap3pandora_snd_data.dev = &omap3pandora_snd_device->dev; + *(unsigned int *)omap_mcbsp_dai[0].private_data = 1; /* McBSP2 */ + *(unsigned int *)omap_mcbsp_dai[1].private_data = 3; /* McBSP4 */ + + ret = platform_device_add(omap3pandora_snd_device); + if (ret) { + pr_err(PREFIX "Unable to add platform device\n"); + goto fail2; + } + + return 0; + +fail2: + platform_device_put(omap3pandora_snd_device); +fail1: + gpio_free(OMAP3_PANDORA_AMP_POWER_GPIO); +fail0: + gpio_free(OMAP3_PANDORA_DAC_POWER_GPIO); + return ret; +} +module_init(omap3pandora_soc_init); + +static void __exit omap3pandora_soc_exit(void) +{ + platform_device_unregister(omap3pandora_snd_device); + gpio_free(OMAP3_PANDORA_AMP_POWER_GPIO); + gpio_free(OMAP3_PANDORA_DAC_POWER_GPIO); +} +module_exit(omap3pandora_soc_exit); + +MODULE_AUTHOR("Grazvydas Ignotas <notasas@gmail.com>"); +MODULE_DESCRIPTION("ALSA SoC OMAP3 Pandora"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/omap/osk5912.c b/sound/soc/omap/osk5912.c index 0fe73379689..845bf41335b 100644 --- a/sound/soc/omap/osk5912.c +++ b/sound/soc/omap/osk5912.c @@ -143,16 +143,16 @@ static struct snd_soc_dai_link osk_dai = { }; /* Audio machine driver */ -static struct snd_soc_machine snd_soc_machine_osk = { +static struct snd_soc_card snd_soc_card_osk = { .name = "OSK5912", + .platform = &omap_soc_platform, .dai_link = &osk_dai, .num_links = 1, }; /* Audio subsystem */ static struct snd_soc_device osk_snd_devdata = { - .machine = &snd_soc_machine_osk, - .platform = &omap_soc_platform, + .card = &snd_soc_card_osk, .codec_dev = &soc_codec_dev_tlv320aic23, }; diff --git a/sound/soc/omap/overo.c b/sound/soc/omap/overo.c new file mode 100644 index 00000000000..a72dc4e159e --- /dev/null +++ b/sound/soc/omap/overo.c @@ -0,0 +1,148 @@ +/* + * overo.c -- SoC audio for Gumstix Overo + * + * Author: Steve Sakoman <steve@sakoman.com> + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include <linux/clk.h> +#include <linux/platform_device.h> +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/soc.h> +#include <sound/soc-dapm.h> + +#include <asm/mach-types.h> +#include <mach/hardware.h> +#include <mach/gpio.h> +#include <mach/mcbsp.h> + +#include "omap-mcbsp.h" +#include "omap-pcm.h" +#include "../codecs/twl4030.h" + +static int overo_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->dai->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + int ret; + + /* 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) { + printk(KERN_ERR "can't set codec DAI configuration\n"); + 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) { + printk(KERN_ERR "can't set cpu DAI configuration\n"); + return ret; + } + + /* Set the codec system clock for DAC and ADC */ + ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000, + SND_SOC_CLOCK_IN); + if (ret < 0) { + printk(KERN_ERR "can't set codec system clock\n"); + return ret; + } + + return 0; +} + +static struct snd_soc_ops overo_ops = { + .hw_params = overo_hw_params, +}; + +/* Digital audio interface glue - connects codec <--> CPU */ +static struct snd_soc_dai_link overo_dai = { + .name = "TWL4030", + .stream_name = "TWL4030", + .cpu_dai = &omap_mcbsp_dai[0], + .codec_dai = &twl4030_dai, + .ops = &overo_ops, +}; + +/* Audio machine driver */ +static struct snd_soc_card snd_soc_card_overo = { + .name = "overo", + .platform = &omap_soc_platform, + .dai_link = &overo_dai, + .num_links = 1, +}; + +/* Audio subsystem */ +static struct snd_soc_device overo_snd_devdata = { + .card = &snd_soc_card_overo, + .codec_dev = &soc_codec_dev_twl4030, +}; + +static struct platform_device *overo_snd_device; + +static int __init overo_soc_init(void) +{ + int ret; + + if (!machine_is_overo()) { + pr_debug("Not Overo!\n"); + return -ENODEV; + } + printk(KERN_INFO "overo SoC init\n"); + + overo_snd_device = platform_device_alloc("soc-audio", -1); + if (!overo_snd_device) { + printk(KERN_ERR "Platform device allocation failed\n"); + return -ENOMEM; + } + + platform_set_drvdata(overo_snd_device, &overo_snd_devdata); + overo_snd_devdata.dev = &overo_snd_device->dev; + *(unsigned int *)overo_dai.cpu_dai->private_data = 1; /* McBSP2 */ + + ret = platform_device_add(overo_snd_device); + if (ret) + goto err1; + + return 0; + +err1: + printk(KERN_ERR "Unable to add platform device\n"); + platform_device_put(overo_snd_device); + + return ret; +} +module_init(overo_soc_init); + +static void __exit overo_soc_exit(void) +{ + platform_device_unregister(overo_snd_device); +} +module_exit(overo_soc_exit); + +MODULE_AUTHOR("Steve Sakoman <steve@sakoman.com>"); +MODULE_DESCRIPTION("ALSA SoC overo"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/omap/sdp3430.c b/sound/soc/omap/sdp3430.c new file mode 100644 index 00000000000..ad97836818b --- /dev/null +++ b/sound/soc/omap/sdp3430.c @@ -0,0 +1,152 @@ +/* + * sdp3430.c -- SoC audio for TI OMAP3430 SDP + * + * Author: Misael Lopez Cruz <x0052729@ti.com> + * + * Based on: + * Author: Steve Sakoman <steve@sakoman.com> + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include <linux/clk.h> +#include <linux/platform_device.h> +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/soc.h> +#include <sound/soc-dapm.h> + +#include <asm/mach-types.h> +#include <mach/hardware.h> +#include <mach/gpio.h> +#include <mach/mcbsp.h> + +#include "omap-mcbsp.h" +#include "omap-pcm.h" +#include "../codecs/twl4030.h" + +static int sdp3430_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->dai->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + int ret; + + /* 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) { + printk(KERN_ERR "can't set codec DAI configuration\n"); + 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) { + printk(KERN_ERR "can't set cpu DAI configuration\n"); + return ret; + } + + /* Set the codec system clock for DAC and ADC */ + ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000, + SND_SOC_CLOCK_IN); + if (ret < 0) { + printk(KERN_ERR "can't set codec system clock\n"); + return ret; + } + + return 0; +} + +static struct snd_soc_ops sdp3430_ops = { + .hw_params = sdp3430_hw_params, +}; + +/* Digital audio interface glue - connects codec <--> CPU */ +static struct snd_soc_dai_link sdp3430_dai = { + .name = "TWL4030", + .stream_name = "TWL4030", + .cpu_dai = &omap_mcbsp_dai[0], + .codec_dai = &twl4030_dai, + .ops = &sdp3430_ops, +}; + +/* Audio machine driver */ +static struct snd_soc_machine snd_soc_machine_sdp3430 = { + .name = "SDP3430", + .platform = &omap_soc_platform, + .dai_link = &sdp3430_dai, + .num_links = 1, +}; + +/* Audio subsystem */ +static struct snd_soc_device sdp3430_snd_devdata = { + .machine = &snd_soc_machine_sdp3430, + .codec_dev = &soc_codec_dev_twl4030, +}; + +static struct platform_device *sdp3430_snd_device; + +static int __init sdp3430_soc_init(void) +{ + int ret; + + if (!machine_is_omap_3430sdp()) { + pr_debug("Not SDP3430!\n"); + return -ENODEV; + } + printk(KERN_INFO "SDP3430 SoC init\n"); + + sdp3430_snd_device = platform_device_alloc("soc-audio", -1); + if (!sdp3430_snd_device) { + printk(KERN_ERR "Platform device allocation failed\n"); + return -ENOMEM; + } + + platform_set_drvdata(sdp3430_snd_device, &sdp3430_snd_devdata); + sdp3430_snd_devdata.dev = &sdp3430_snd_device->dev; + *(unsigned int *)sdp3430_dai.cpu_dai->private_data = 1; /* McBSP2 */ + + ret = platform_device_add(sdp3430_snd_device); + if (ret) + goto err1; + + return 0; + +err1: + printk(KERN_ERR "Unable to add platform device\n"); + platform_device_put(sdp3430_snd_device); + + return ret; +} +module_init(sdp3430_soc_init); + +static void __exit sdp3430_soc_exit(void) +{ + platform_device_unregister(sdp3430_snd_device); +} +module_exit(sdp3430_soc_exit); + +MODULE_AUTHOR("Misael Lopez Cruz <x0052729@ti.com>"); +MODULE_DESCRIPTION("ALSA SoC SDP3430"); +MODULE_LICENSE("GPL"); + |