On Fri, 2010-01-22 at 17:15 -0600, Candelaria Villareal, Jorge wrote: > From: Misael Lopez Cruz <x0052729@xxxxxx> > > 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@xxxxxx> > Signed-off-by: Margarita Olaya <x0080101@xxxxxx> > Signed-off-by: Jorge Eduardo Candelaria <x0107209@xxxxxx> > --- > 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@xxxxxx> > + * Contact: Jorge Eduardo Candelaria <x0107209@xxxxxx> > + * Margarita Olaya <magi.olaya@xxxxxx> > + * > + * 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@xxxxxx>"); > +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@xxxxxx> > + * > + * 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__ */ -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html