On Fri, 2010-01-22 at 17:15 -0600, Candelaria Villareal, Jorge wrote:
From: Misael Lopez Cruz x0052729@ti.com
McPDM platform driver is configured to use sDMA in order to transfer to/from memory. Support for interfacing with ABE will be added later.
McPDM dai currently supports up to 4 downlink channels and 2 uplink channels simultaneously, as well as 88.2 and 96 KHz, and a sample size of 32 bits.
Signed-off-by: Misael Lopez Cruz x0052729@ti.com Signed-off-by: Margarita Olaya x0080101@ti.com Signed-off-by: Jorge Eduardo Candelaria x0107209@ti.com
sound/soc/omap/Makefile | 2 +- sound/soc/omap/omap-mcpdm.c | 250 +++++++++++++++++++++++++++++++++++++++++++ sound/soc/omap/omap-mcpdm.h | 29 +++++ 3 files changed, 280 insertions(+), 1 deletions(-) create mode 100644 sound/soc/omap/omap-mcpdm.c create mode 100644 sound/soc/omap/omap-mcpdm.h
diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile index bf8b388..d6382fa 100644 --- a/sound/soc/omap/Makefile +++ b/sound/soc/omap/Makefile @@ -1,7 +1,7 @@ # 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-mcpdm-objs := mcpdm.o omap-mcpdm.o
obj-$(CONFIG_SND_OMAP_SOC) += snd-soc-omap.o obj-$(CONFIG_SND_OMAP_SOC_MCBSP) += snd-soc-omap-mcbsp.o diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c new file mode 100644 index 0000000..180cca6 --- /dev/null +++ b/sound/soc/omap/omap-mcpdm.c @@ -0,0 +1,250 @@ +/*
- omap-mcpdm.c -- OMAP ALSA SoC DAI driver using McPDM port
- Copyright (C) 2009 Texas Instruments
- Author: Misael Lopez Cruz x0052729@ti.com
- Contact: Jorge Eduardo Candelaria x0107209@ti.com
Margarita Olaya <magi.olaya@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 <mach/mcbsp.h> +#include "mcpdm.h" +#include "omap-mcpdm.h" +#include "omap-pcm.h"
+struct omap_mcpdm_data {
- struct omap_mcpdm_link *links;
- int active;
+};
+static struct omap_mcpdm_link omap_mcpdm_links[] = {
- /* downlink */
- {
.irq_mask = MCPDM_DN_IRQ_EMPTY | MCPDM_DN_IRQ_FULL,
.threshold = 1,
.format = PDMOUTFORMAT_LJUST,
- },
- /* uplink */
- {
.irq_mask = MCPDM_UP_IRQ_EMPTY | MCPDM_UP_IRQ_FULL,
.threshold = 1,
.format = PDMOUTFORMAT_LJUST,
- },
+};
+static struct omap_mcpdm_data mcpdm_data = {
- .links = omap_mcpdm_links,
- .active = 0,
+};
+/*
- Stream DMA parameters
- */
+static struct omap_pcm_dma_data omap_mcpdm_dai_dma_params[] = {
- {
.name = "Audio downlink",
.dma_req = OMAP44XX_DMA_MCPDM_DL,
.data_type = OMAP_DMA_DATA_TYPE_S32,
.sync_mode = OMAP_DMA_SYNC_PACKET,
.packet_size = 16,
.port_addr = OMAP44XX_MCPDM_L3_BASE + MCPDM_DN_DATA,
- },
- {
.name = "Audio uplink",
.dma_req = OMAP44XX_DMA_MCPDM_UP,
.data_type = OMAP_DMA_DATA_TYPE_S32,
.sync_mode = OMAP_DMA_SYNC_PACKET,
.packet_size = 16,
.port_addr = OMAP44XX_MCPDM_L3_BASE + MCPDM_UP_DATA,
- },
+};
+static int omap_mcpdm_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();
Will anything else use this hw interface other than ALSA audio ? If not, the request is probably better in the machine driver probe().
- return err;
+}
+static void omap_mcpdm_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();
ditto.
+}
+static int omap_mcpdm_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_mcpdm_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 stream = substream->stream;
- int channels, err, link_mask = 0;
- cpu_dai->dma_data = &omap_mcpdm_dai_dma_params[stream];
- channels = params_channels(params);
- switch (channels) {
- case 4:
if (stream)
stream is either PLAYBACK or CAPTURE here.
/* up to 2 channels for uplink */
return -EINVAL;
link_mask |= 1 << 3;
- case 3:
if (stream)
/* up to 2 channels for uplink */
return -EINVAL;
link_mask |= 1 << 2;
- case 2:
link_mask |= 1 << 1;
- case 1:
link_mask |= 1 << 0;
break;
- default:
/* unsupported number of channels */
return -EINVAL;
- }
- if (stream) {
ditto
mcpdm_links[stream].channels = link_mask << 0;
err = omap_mcpdm_set_uplink(&mcpdm_links[stream]);
- } else {
mcpdm_links[stream].channels = link_mask << 3;
err = omap_mcpdm_set_downlink(&mcpdm_links[stream]);
- }
- return err;
+}
+static int omap_mcpdm_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)
ditto
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_mcpdm_dai_ops = {
- .startup = omap_mcpdm_dai_startup,
- .shutdown = omap_mcpdm_dai_shutdown,
- .trigger = omap_mcpdm_dai_trigger,
- .hw_params = omap_mcpdm_dai_hw_params,
- .hw_free = omap_mcpdm_dai_hw_free,
+};
+#define OMAP_MCPDM_RATES (SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
Is this the link rate or sample rate ? What about slower rates ?
+#define OMAP_MCPDM_FORMATS (SNDRV_PCM_FMTBIT_S32_LE)
Is this the link format or sample format ? What about 16bit ?
+struct snd_soc_dai omap_mcpdm_dai = {
- .name = "omap-mcpdm",
- .id = -1,
- .playback = {
.channels_min = 1,
.channels_max = 4,
.rates = OMAP_MCPDM_RATES,
.formats = OMAP_MCPDM_FORMATS,
- },
- .capture = {
.channels_min = 1,
.channels_max = 2,
.rates = OMAP_MCPDM_RATES,
.formats = OMAP_MCPDM_FORMATS,
- },
- .ops = &omap_mcpdm_dai_ops,
- .private_data = &mcpdm_data,
+}; +EXPORT_SYMBOL_GPL(omap_mcpdm_dai);
+static int __init snd_omap_mcpdm_init(void) +{
- return snd_soc_register_dai(&omap_mcpdm_dai);
+} +module_init(snd_omap_mcpdm_init);
+static void __exit snd_omap_mcpdm_exit(void) +{
- snd_soc_unregister_dai(&omap_mcpdm_dai);
+} +module_exit(snd_omap_mcpdm_exit);
+MODULE_AUTHOR("Misael Lopez Cruz x0052729@ti.com"); +MODULE_DESCRIPTION("OMAP PDM SoC Interface"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/omap/omap-mcpdm.h b/sound/soc/omap/omap-mcpdm.h new file mode 100644 index 0000000..73b80d5 --- /dev/null +++ b/sound/soc/omap/omap-mcpdm.h @@ -0,0 +1,29 @@ +/*
- omap-mcpdm.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__
+extern struct snd_soc_dai omap_mcpdm_dai;
+#endif /* End of __OMAP_MCPDM_H__ */