diff options
author | Misael Lopez Cruz <x0052729@ti.com> | 2009-08-13 11:28:57 -0500 |
---|---|---|
committer | Misael Lopez Cruz <x0052729@ti.com> | 2009-08-13 23:44:28 -0500 |
commit | 40f6b0aa6e977a13115d8877cac8c0732896c4df (patch) | |
tree | a8f398afef8cb4b88480e59c643265ba8ec82396 | |
parent | 23ad46f243b9b71c2e1dcbcf8e70a3007edd6d7f (diff) |
ASoC: OMAP4: Add ABE DAI driver
Initial version of ABE DAI platform driver.
Signed-off-by: Misael Lopez Cruz <x0052729@ti.com>
-rw-r--r-- | sound/soc/omap/Kconfig | 2 | ||||
-rw-r--r-- | sound/soc/omap/Makefile | 4 | ||||
-rw-r--r-- | sound/soc/omap/omap-abe.c | 314 | ||||
-rw-r--r-- | sound/soc/omap/omap-abe.h | 35 |
4 files changed, 352 insertions, 3 deletions
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig index cb50c0afdcf7..4d9cf19ea4d4 100644 --- a/sound/soc/omap/Kconfig +++ b/sound/soc/omap/Kconfig @@ -6,7 +6,7 @@ config SND_OMAP_SOC_MCBSP tristate select OMAP_MCBSP -config SND_OMAP_SOC_MCPDM +config SND_OMAP_SOC_ABE tristate config SND_OMAP_SOC_N810 diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile index 7c5a00147c1d..408146187922 100644 --- a/sound/soc/omap/Makefile +++ b/sound/soc/omap/Makefile @@ -1,11 +1,11 @@ # OMAP Platform Support snd-soc-omap-objs := omap-pcm.o snd-soc-omap-mcbsp-objs := omap-mcbsp.o -snd-soc-omap-mcpdm-objs := mcpdm.o +snd-soc-omap-abe-objs := mcpdm.o omap-abe.o obj-$(CONFIG_SND_OMAP_SOC) += snd-soc-omap.o obj-$(CONFIG_SND_OMAP_SOC_MCBSP) += snd-soc-omap-mcbsp.o -obj-$(CONFIG_SND_OMAP_SOC_MCPDM) += snd-soc-omap-mcpdm.o +obj-$(CONFIG_SND_OMAP_SOC_ABE) += snd-soc-omap-abe.o # OMAP Machine Support snd-soc-n810-objs := n810.o diff --git a/sound/soc/omap/omap-abe.c b/sound/soc/omap/omap-abe.c new file mode 100644 index 000000000000..c4b0eec35413 --- /dev/null +++ b/sound/soc/omap/omap-abe.c @@ -0,0 +1,314 @@ +/* + * omap-abe.c -- OMAP ALSA SoC DAI driver using Audio Backend + * + * Copyright (C) 2009 Texas Instruments + * + * Contact: Misael Lopez Cruz <x0052729@ti.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/init.h> +#include <linux/module.h> +#include <linux/device.h> +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/initval.h> +#include <sound/soc.h> + +#include <mach/control.h> +#include <mach/dma.h> +#include "mcpdm.h" +#include "omap-pcm.h" +#include "omap-abe.h" +#include "../codecs/abe/abe_main.h" + +#define OMAP_ABE_FORMATS (SNDRV_PCM_FMTBIT_S32_LE) + +struct omap_mcpdm_data { + struct omap_mcpdm_link *links; + int active; +}; + +static struct omap_mcpdm_link omap_mcpdm_links[] = { + /* downlink */ + { + .irq_mask = DN_IRQ_EMTPY | DN_IRQ_FULL, + .threshold = 1, + .format = PDMOUTFORMAT_LJUST, + .channels = PDM_DN_MASK | PDM_CMD_MASK, + }, + /* uplink */ + { + .irq_mask = UP_IRQ_EMPTY | UP_IRQ_FULL, + .threshold = 1, + .format = PDMOUTFORMAT_LJUST, + .channels = PDM_UP_MASK | PDM_STATUS_MASK, + }, +}; + +static struct omap_mcpdm_data mcpdm_data = { + .links = omap_mcpdm_links, + .active = 0, +}; + +/* + * Stream DMA parameters + */ +static struct omap_pcm_dma_data omap_abe_dai_dma_params[] = { + { + .name = "Audio downlink", + .dma_req = OMAP44XX_DMM_ABE_DMAREQ0, + .data_type = OMAP_DMA_DATA_TYPE_S32, + .sync_mode = OMAP_DMA_SYNC_PACKET, + }, + { + .name = "Audio uplink", + .dma_req = OMAP44XX_DMM_ABE_DMAREQ2, + .data_type = OMAP_DMA_DATA_TYPE_S32, + .sync_mode = OMAP_DMA_SYNC_PACKET, + }, +}; + +static int omap_abe_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; + int err = 0; + + if (!cpu_dai->active) + err = omap_mcpdm_request(); + + return err; +} + +static void omap_abe_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; + + if (!cpu_dai->active) + omap_mcpdm_free(); +} + +static int omap_abe_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; + struct omap_mcpdm_data *mcpdm_priv = cpu_dai->private_data; + int stream = substream->stream; + int err = 0; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + if (!mcpdm_priv->active++) + omap_mcpdm_start(stream); + break; + + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + if (!--mcpdm_priv->active) + omap_mcpdm_stop(stream); + break; + default: + err = -EINVAL; + } + + return err; +} + +static int omap_abe_dai_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 *cpu_dai = rtd->dai->cpu_dai; + struct omap_mcpdm_data *mcpdm_priv = cpu_dai->private_data; + struct omap_mcpdm_link *mcpdm_links = mcpdm_priv->links; + int err, stream = substream->stream; + abe_dma_t dma_params; + + /* get abe dma data */ + switch (cpu_dai->id) { + case OMAP_ABE_MM_DAI: + if (stream) + abe_read_port_address(MM_UL2_PORT, &dma_params); + else + abe_read_port_address(MM_DL_PORT, &dma_params); + break; + case OMAP_ABE_MM_EXT_DAI: + if (stream) + return -EINVAL; + else + abe_read_port_address(TONES_DL_PORT, &dma_params); + break; + case OMAP_ABE_VOICE_DAI: + if (stream) + abe_read_port_address(VX_UL_PORT, &dma_params); + else + abe_read_port_address(VX_DL_PORT, &dma_params); + break; + case OMAP_ABE_DIG_UPLINK_DAI: + if (stream) + abe_read_port_address(MM_UL_PORT, &dma_params); + else + return -EINVAL; + break; + case OMAP_ABE_VIB_DAI: + if (stream) + return -EINVAL; + else + abe_read_port_address(VIB_DL_PORT, &dma_params); + default: + return -EINVAL; + } + + omap_abe_dai_dma_params[stream].port_addr = + (unsigned long)dma_params.data; + omap_abe_dai_dma_params[stream].packet_size = dma_params.iter; + cpu_dai->dma_data = &omap_abe_dai_dma_params[stream]; + + if (stream) + err = omap_mcpdm_set_uplink(&mcpdm_links[stream]); + else + err = omap_mcpdm_set_downlink(&mcpdm_links[stream]); + + return err; +} + +static int omap_abe_dai_hw_free(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; + struct omap_mcpdm_data *mcpdm_priv = cpu_dai->private_data; + struct omap_mcpdm_link *mcpdm_links = mcpdm_priv->links; + int err; + + if (substream->stream) + err = omap_mcpdm_clr_uplink(&mcpdm_links[substream->stream]); + else + err = omap_mcpdm_clr_downlink(&mcpdm_links[substream->stream]); + + return err; +} + +static struct snd_soc_dai_ops omap_abe_dai_ops = { + .startup = omap_abe_dai_startup, + .shutdown = omap_abe_dai_shutdown, + .trigger = omap_abe_dai_trigger, + .hw_params = omap_abe_dai_hw_params, + .hw_free = omap_abe_dai_hw_free, +}; + +struct snd_soc_dai omap_abe_dai[] = { + { + .name = "omap-abe-mm", + .id = OMAP_ABE_MM_DAI, + .playback = { + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, + .formats = OMAP_ABE_FORMATS, + }, + .capture = { + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_48000, + .formats = OMAP_ABE_FORMATS, + }, + .ops = &omap_abe_dai_ops, + .private_data = &mcpdm_data, + }, + { + .name = "omap-abe-mm-ext", + .id = OMAP_ABE_MM_EXT_DAI, + .playback = { + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, + .formats = OMAP_ABE_FORMATS, + }, + .ops = &omap_abe_dai_ops, + .private_data = &mcpdm_data, + }, + { + .name = "omap-abe-voice", + .id = OMAP_ABE_VOICE_DAI, + .playback = { + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000, + .formats = OMAP_ABE_FORMATS, + }, + .capture = { + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000, + .formats = OMAP_ABE_FORMATS, + }, + .ops = &omap_abe_dai_ops, + .private_data = &mcpdm_data, + }, + { + .name = "omap-abe-dig-ul", + .id = OMAP_ABE_DIG_UPLINK_DAI, + .capture = { + .channels_min = 2, + .channels_max = 8, + .rates = SNDRV_PCM_RATE_48000, + .formats = OMAP_ABE_FORMATS, + }, + .ops = &omap_abe_dai_ops, + .private_data = &mcpdm_data, + }, + { + .name = "omap-abe-vib", + .id = OMAP_ABE_VIB_DAI, + .playback = { + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_48000, + .formats = OMAP_ABE_FORMATS, + }, + .ops = &omap_abe_dai_ops, + .private_data = &mcpdm_data, + }, +}; +EXPORT_SYMBOL_GPL(omap_abe_dai); + +static int __init snd_omap_abe_init(void) +{ + return snd_soc_register_dais(omap_abe_dai, ARRAY_SIZE(omap_abe_dai)); +} +module_init(snd_omap_abe_init); + +static void __exit snd_omap_abe_exit(void) +{ + snd_soc_unregister_dais(omap_abe_dai, ARRAY_SIZE(omap_abe_dai)); +} +module_exit(snd_omap_abe_exit); + +MODULE_AUTHOR("Misael Lopez Cruz <x0052729@ti.com>"); +MODULE_DESCRIPTION("OMAP ABE SoC Interface"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/omap/omap-abe.h b/sound/soc/omap/omap-abe.h new file mode 100644 index 000000000000..1c23b3b7fe36 --- /dev/null +++ b/sound/soc/omap/omap-abe.h @@ -0,0 +1,35 @@ +/* + * omap-abe.h + * + * Copyright (C) 2009 Texas Instruments + * + * Contact: Misael Lopez Cruz <x0052729@ti.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 + * + */ + +#ifndef __OMAP_MCPDM_H__ +#define __OMAP_MCPDM_H__ + +#define OMAP_ABE_MM_DAI 0 +#define OMAP_ABE_MM_EXT_DAI 1 +#define OMAP_ABE_VOICE_DAI 2 +#define OMAP_ABE_DIG_UPLINK_DAI 3 +#define OMAP_ABE_VIB_DAI 4 + +extern struct snd_soc_dai omap_abe_dai[]; + +#endif /* End of __OMAP_MCPDM_H__ */ |