diff options
Diffstat (limited to 'sound/soc/omap')
-rw-r--r-- | sound/soc/omap/Makefile | 2 | ||||
-rw-r--r-- | sound/soc/omap/am3517evm.c | 50 | ||||
-rw-r--r-- | sound/soc/omap/ams-delta.c | 1 | ||||
-rw-r--r-- | sound/soc/omap/igep0020.c | 23 | ||||
-rw-r--r-- | sound/soc/omap/mcpdm.c | 470 | ||||
-rw-r--r-- | sound/soc/omap/mcpdm.h | 153 | ||||
-rw-r--r-- | sound/soc/omap/n810.c | 42 | ||||
-rw-r--r-- | sound/soc/omap/omap-mcbsp.c | 27 | ||||
-rw-r--r-- | sound/soc/omap/omap-mcpdm.c | 481 | ||||
-rw-r--r-- | sound/soc/omap/omap-mcpdm.h | 107 | ||||
-rw-r--r-- | sound/soc/omap/omap-pcm.c | 8 | ||||
-rw-r--r-- | sound/soc/omap/omap3evm.c | 23 | ||||
-rw-r--r-- | sound/soc/omap/omap3pandora.c | 28 | ||||
-rw-r--r-- | sound/soc/omap/osk5912.c | 50 | ||||
-rw-r--r-- | sound/soc/omap/overo.c | 23 | ||||
-rw-r--r-- | sound/soc/omap/rx51.c | 22 | ||||
-rw-r--r-- | sound/soc/omap/sdp3430.c | 88 | ||||
-rw-r--r-- | sound/soc/omap/sdp4430.c | 47 | ||||
-rw-r--r-- | sound/soc/omap/zoom2.c | 96 |
19 files changed, 585 insertions, 1156 deletions
diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile index 59e2c8d1e38..052fd758722 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 := omap-mcpdm.o mcpdm.o +snd-soc-omap-mcpdm-objs := omap-mcpdm.o snd-soc-omap-hdmi-objs := omap-hdmi.o obj-$(CONFIG_SND_OMAP_SOC) += snd-soc-omap.o diff --git a/sound/soc/omap/am3517evm.c b/sound/soc/omap/am3517evm.c index 73dde4a1adc..8da55e91645 100644 --- a/sound/soc/omap/am3517evm.c +++ b/sound/soc/omap/am3517evm.c @@ -43,26 +43,6 @@ static int am3517evm_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai = rtd->cpu_dai; int ret; - /* Set codec DAI configuration */ - ret = snd_soc_dai_set_fmt(codec_dai, - SND_SOC_DAIFMT_DSP_B | - 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_DSP_B | - 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, CODEC_CLOCK, SND_SOC_CLOCK_IN); @@ -110,28 +90,6 @@ static const struct snd_soc_dapm_route audio_map[] = { {"MICIN", NULL, "Mic In"}, }; -static int am3517evm_aic23_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - - /* Add am3517-evm specific widgets */ - snd_soc_dapm_new_controls(dapm, tlv320aic23_dapm_widgets, - ARRAY_SIZE(tlv320aic23_dapm_widgets)); - - /* Set up davinci-evm specific audio path audio_map */ - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - - /* always connected */ - snd_soc_dapm_enable_pin(dapm, "Line Out"); - snd_soc_dapm_enable_pin(dapm, "Line In"); - snd_soc_dapm_enable_pin(dapm, "Mic In"); - - snd_soc_dapm_sync(dapm); - - return 0; -} - /* Digital audio interface glue - connects codec <--> CPU */ static struct snd_soc_dai_link am3517evm_dai = { .name = "TLV320AIC23", @@ -140,7 +98,8 @@ static struct snd_soc_dai_link am3517evm_dai = { .codec_dai_name = "tlv320aic23-hifi", .platform_name = "omap-pcm-audio", .codec_name = "tlv320aic23-codec.2-001a", - .init = am3517evm_aic23_init, + .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBM_CFM, .ops = &am3517evm_ops, }; @@ -149,6 +108,11 @@ static struct snd_soc_card snd_soc_am3517evm = { .name = "am3517evm", .dai_link = &am3517evm_dai, .num_links = 1, + + .dapm_widgets = tlv320aic23_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(tlv320aic23_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static struct platform_device *am3517evm_snd_device; diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c index 0aa475f92ef..dcb7b689a4e 100644 --- a/sound/soc/omap/ams-delta.c +++ b/sound/soc/omap/ams-delta.c @@ -569,7 +569,6 @@ static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd) snd_soc_dapm_disable_pin(dapm, "Speaker"); snd_soc_dapm_disable_pin(dapm, "AGCIN"); snd_soc_dapm_disable_pin(dapm, "AGCOUT"); - snd_soc_dapm_sync(dapm); /* Add virtual switch */ ret = snd_soc_add_controls(codec, ams_delta_audio_controls, diff --git a/sound/soc/omap/igep0020.c b/sound/soc/omap/igep0020.c index 0ae34702995..84615a7de6a 100644 --- a/sound/soc/omap/igep0020.c +++ b/sound/soc/omap/igep0020.c @@ -38,29 +38,8 @@ static int igep2_hw_params(struct snd_pcm_substream *substream, { 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; - /* 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); @@ -84,6 +63,8 @@ static struct snd_soc_dai_link igep2_dai = { .codec_dai_name = "twl4030-hifi", .platform_name = "omap-pcm-audio", .codec_name = "twl4030-codec", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBM_CFM, .ops = &igep2_ops, }; diff --git a/sound/soc/omap/mcpdm.c b/sound/soc/omap/mcpdm.c deleted file mode 100644 index 50e59194ad8..00000000000 --- a/sound/soc/omap/mcpdm.c +++ /dev/null @@ -1,470 +0,0 @@ -/* - * mcpdm.c -- McPDM interface driver - * - * Author: Jorge Eduardo Candelaria <x0107209@ti.com> - * Copyright (C) 2009 - Texas Instruments, Inc. - * - * 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/module.h> -#include <linux/init.h> -#include <linux/device.h> -#include <linux/platform_device.h> -#include <linux/wait.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/err.h> -#include <linux/clk.h> -#include <linux/delay.h> -#include <linux/io.h> -#include <linux/irq.h> - -#include "mcpdm.h" - -static struct omap_mcpdm *mcpdm; - -static inline void omap_mcpdm_write(u16 reg, u32 val) -{ - __raw_writel(val, mcpdm->io_base + reg); -} - -static inline int omap_mcpdm_read(u16 reg) -{ - return __raw_readl(mcpdm->io_base + reg); -} - -static void omap_mcpdm_reg_dump(void) -{ - dev_dbg(mcpdm->dev, "***********************\n"); - dev_dbg(mcpdm->dev, "IRQSTATUS_RAW: 0x%04x\n", - omap_mcpdm_read(MCPDM_IRQSTATUS_RAW)); - dev_dbg(mcpdm->dev, "IRQSTATUS: 0x%04x\n", - omap_mcpdm_read(MCPDM_IRQSTATUS)); - dev_dbg(mcpdm->dev, "IRQENABLE_SET: 0x%04x\n", - omap_mcpdm_read(MCPDM_IRQENABLE_SET)); - dev_dbg(mcpdm->dev, "IRQENABLE_CLR: 0x%04x\n", - omap_mcpdm_read(MCPDM_IRQENABLE_CLR)); - dev_dbg(mcpdm->dev, "IRQWAKE_EN: 0x%04x\n", - omap_mcpdm_read(MCPDM_IRQWAKE_EN)); - dev_dbg(mcpdm->dev, "DMAENABLE_SET: 0x%04x\n", - omap_mcpdm_read(MCPDM_DMAENABLE_SET)); - dev_dbg(mcpdm->dev, "DMAENABLE_CLR: 0x%04x\n", - omap_mcpdm_read(MCPDM_DMAENABLE_CLR)); - dev_dbg(mcpdm->dev, "DMAWAKEEN: 0x%04x\n", - omap_mcpdm_read(MCPDM_DMAWAKEEN)); - dev_dbg(mcpdm->dev, "CTRL: 0x%04x\n", - omap_mcpdm_read(MCPDM_CTRL)); - dev_dbg(mcpdm->dev, "DN_DATA: 0x%04x\n", - omap_mcpdm_read(MCPDM_DN_DATA)); - dev_dbg(mcpdm->dev, "UP_DATA: 0x%04x\n", - omap_mcpdm_read(MCPDM_UP_DATA)); - dev_dbg(mcpdm->dev, "FIFO_CTRL_DN: 0x%04x\n", - omap_mcpdm_read(MCPDM_FIFO_CTRL_DN)); - dev_dbg(mcpdm->dev, "FIFO_CTRL_UP: 0x%04x\n", - omap_mcpdm_read(MCPDM_FIFO_CTRL_UP)); - dev_dbg(mcpdm->dev, "DN_OFFSET: 0x%04x\n", - omap_mcpdm_read(MCPDM_DN_OFFSET)); - dev_dbg(mcpdm->dev, "***********************\n"); -} - -/* - * Takes the McPDM module in and out of reset state. - * Uplink and downlink can be reset individually. - */ -static void omap_mcpdm_reset_capture(int reset) -{ - int ctrl = omap_mcpdm_read(MCPDM_CTRL); - - if (reset) - ctrl |= SW_UP_RST; - else - ctrl &= ~SW_UP_RST; - - omap_mcpdm_write(MCPDM_CTRL, ctrl); -} - -static void omap_mcpdm_reset_playback(int reset) -{ - int ctrl = omap_mcpdm_read(MCPDM_CTRL); - - if (reset) - ctrl |= SW_DN_RST; - else - ctrl &= ~SW_DN_RST; - - omap_mcpdm_write(MCPDM_CTRL, ctrl); -} - -/* - * Enables the transfer through the PDM interface to/from the Phoenix - * codec by enabling the corresponding UP or DN channels. - */ -void omap_mcpdm_start(int stream) -{ - int ctrl = omap_mcpdm_read(MCPDM_CTRL); - - if (stream) - ctrl |= mcpdm->up_channels; - else - ctrl |= mcpdm->dn_channels; - - omap_mcpdm_write(MCPDM_CTRL, ctrl); -} - -/* - * Disables the transfer through the PDM interface to/from the Phoenix - * codec by disabling the corresponding UP or DN channels. - */ -void omap_mcpdm_stop(int stream) -{ - int ctrl = omap_mcpdm_read(MCPDM_CTRL); - - if (stream) - ctrl &= ~mcpdm->up_channels; - else - ctrl &= ~mcpdm->dn_channels; - - omap_mcpdm_write(MCPDM_CTRL, ctrl); -} - -/* - * Configures McPDM uplink for audio recording. - * This function should be called before omap_mcpdm_start. - */ -int omap_mcpdm_capture_open(struct omap_mcpdm_link *uplink) -{ - int irq_mask = 0; - int ctrl; - - if (!uplink) - return -EINVAL; - - mcpdm->uplink = uplink; - - /* Enable irq request generation */ - irq_mask |= uplink->irq_mask & MCPDM_UPLINK_IRQ_MASK; - omap_mcpdm_write(MCPDM_IRQENABLE_SET, irq_mask); - - /* Configure uplink threshold */ - if (uplink->threshold > UP_THRES_MAX) - uplink->threshold = UP_THRES_MAX; - - omap_mcpdm_write(MCPDM_FIFO_CTRL_UP, uplink->threshold); - - /* Configure DMA controller */ - omap_mcpdm_write(MCPDM_DMAENABLE_SET, DMA_UP_ENABLE); - - /* Set pdm out format */ - ctrl = omap_mcpdm_read(MCPDM_CTRL); - ctrl &= ~PDMOUTFORMAT; - ctrl |= uplink->format & PDMOUTFORMAT; - - /* Uplink channels */ - mcpdm->up_channels = uplink->channels & (PDM_UP_MASK | PDM_STATUS_MASK); - - omap_mcpdm_write(MCPDM_CTRL, ctrl); - - return 0; -} - -/* - * Configures McPDM downlink for audio playback. - * This function should be called before omap_mcpdm_start. - */ -int omap_mcpdm_playback_open(struct omap_mcpdm_link *downlink) -{ - int irq_mask = 0; - int ctrl; - - if (!downlink) - return -EINVAL; - - mcpdm->downlink = downlink; - - /* Enable irq request generation */ - irq_mask |= downlink->irq_mask & MCPDM_DOWNLINK_IRQ_MASK; - omap_mcpdm_write(MCPDM_IRQENABLE_SET, irq_mask); - - /* Configure uplink threshold */ - if (downlink->threshold > DN_THRES_MAX) - downlink->threshold = DN_THRES_MAX; - - omap_mcpdm_write(MCPDM_FIFO_CTRL_DN, downlink->threshold); - - /* Enable DMA request generation */ - omap_mcpdm_write(MCPDM_DMAENABLE_SET, DMA_DN_ENABLE); - - /* Set pdm out format */ - ctrl = omap_mcpdm_read(MCPDM_CTRL); - ctrl &= ~PDMOUTFORMAT; - ctrl |= downlink->format & PDMOUTFORMAT; - - /* Downlink channels */ - mcpdm->dn_channels = downlink->channels & (PDM_DN_MASK | PDM_CMD_MASK); - - omap_mcpdm_write(MCPDM_CTRL, ctrl); - - return 0; -} - -/* - * Cleans McPDM uplink configuration. - * This function should be called when the stream is closed. - */ -int omap_mcpdm_capture_close(struct omap_mcpdm_link *uplink) -{ - int irq_mask = 0; - - if (!uplink) - return -EINVAL; - - /* Disable irq request generation */ - irq_mask |= uplink->irq_mask & MCPDM_UPLINK_IRQ_MASK; - omap_mcpdm_write(MCPDM_IRQENABLE_CLR, irq_mask); - - /* Disable DMA request generation */ - omap_mcpdm_write(MCPDM_DMAENABLE_CLR, DMA_UP_ENABLE); - - /* Clear Downlink channels */ - mcpdm->up_channels = 0; - - mcpdm->uplink = NULL; - - return 0; -} - -/* - * Cleans McPDM downlink configuration. - * This function should be called when the stream is closed. - */ -int omap_mcpdm_playback_close(struct omap_mcpdm_link *downlink) -{ - int irq_mask = 0; - - if (!downlink) - return -EINVAL; - - /* Disable irq request generation */ - irq_mask |= downlink->irq_mask & MCPDM_DOWNLINK_IRQ_MASK; - omap_mcpdm_write(MCPDM_IRQENABLE_CLR, irq_mask); - - /* Disable DMA request generation */ - omap_mcpdm_write(MCPDM_DMAENABLE_CLR, DMA_DN_ENABLE); - - /* clear Downlink channels */ - mcpdm->dn_channels = 0; - - mcpdm->downlink = NULL; - - return 0; -} - -static irqreturn_t omap_mcpdm_irq_handler(int irq, void *dev_id) -{ - struct omap_mcpdm *mcpdm_irq = dev_id; - int irq_status; - - irq_status = omap_mcpdm_read(MCPDM_IRQSTATUS); - - /* Acknowledge irq event */ - omap_mcpdm_write(MCPDM_IRQSTATUS, irq_status); - - if (irq & MCPDM_DN_IRQ_FULL) { - dev_err(mcpdm_irq->dev, "DN FIFO error %x\n", irq_status); - omap_mcpdm_reset_playback(1); - omap_mcpdm_playback_open(mcpdm_irq->downlink); - omap_mcpdm_reset_playback(0); - } - - if (irq & MCPDM_DN_IRQ_EMPTY) { - dev_err(mcpdm_irq->dev, "DN FIFO error %x\n", irq_status); - omap_mcpdm_reset_playback(1); - omap_mcpdm_playback_open(mcpdm_irq->downlink); - omap_mcpdm_reset_playback(0); - } - - if (irq & MCPDM_DN_IRQ) { - dev_dbg(mcpdm_irq->dev, "DN write request\n"); - } - - if (irq & MCPDM_UP_IRQ_FULL) { - dev_err(mcpdm_irq->dev, "UP FIFO error %x\n", irq_status); - omap_mcpdm_reset_capture(1); - omap_mcpdm_capture_open(mcpdm_irq->uplink); - omap_mcpdm_reset_capture(0); - } - - if (irq & MCPDM_UP_IRQ_EMPTY) { - dev_err(mcpdm_irq->dev, "UP FIFO error %x\n", irq_status); - omap_mcpdm_reset_capture(1); - omap_mcpdm_capture_open(mcpdm_irq->uplink); - omap_mcpdm_reset_capture(0); - } - - if (irq & MCPDM_UP_IRQ) { - dev_dbg(mcpdm_irq->dev, "UP write request\n"); - } - - return IRQ_HANDLED; -} - -int omap_mcpdm_request(void) -{ - int ret; - - clk_enable(mcpdm->clk); - - spin_lock(&mcpdm->lock); - - if (!mcpdm->free) { - dev_err(mcpdm->dev, "McPDM interface is in use\n"); - spin_unlock(&mcpdm->lock); - ret = -EBUSY; - goto err; - } - mcpdm->free = 0; - - spin_unlock(&mcpdm->lock); - - /* Disable lines while request is ongoing */ - omap_mcpdm_write(MCPDM_CTRL, 0x00); - - ret = request_irq(mcpdm->irq, omap_mcpdm_irq_handler, - 0, "McPDM", (void *)mcpdm); - if (ret) { - dev_err(mcpdm->dev, "Request for McPDM IRQ failed\n"); - goto err; - } - - return 0; - -err: - clk_disable(mcpdm->clk); - return ret; -} - -void omap_mcpdm_free(void) -{ - spin_lock(&mcpdm->lock); - if (mcpdm->free) { - dev_err(mcpdm->dev, "McPDM interface is already free\n"); - spin_unlock(&mcpdm->lock); - return; - } - mcpdm->free = 1; - spin_unlock(&mcpdm->lock); - - clk_disable(mcpdm->clk); - - free_irq(mcpdm->irq, (void *)mcpdm); -} - -/* Enable/disable DC offset cancelation for the analog - * headset path (PDM channels 1 and 2). - */ -int omap_mcpdm_set_offset(int offset1, int offset2) -{ - int offset; - - if ((offset1 > DN_OFST_MAX) || (offset2 > DN_OFST_MAX)) - return -EINVAL; - - offset = (offset1 << DN_OFST_RX1) | (offset2 << DN_OFST_RX2); - - /* offset cancellation for channel 1 */ - if (offset1) - offset |= DN_OFST_RX1_EN; - else - offset &= ~DN_OFST_RX1_EN; - - /* offset cancellation for channel 2 */ - if (offset2) - offset |= DN_OFST_RX2_EN; - else - offset &= ~DN_OFST_RX2_EN; - - omap_mcpdm_write(MCPDM_DN_OFFSET, offset); - - return 0; -} - -int __devinit omap_mcpdm_probe(struct platform_device *pdev) -{ - struct resource *res; - int ret = 0; - - mcpdm = kzalloc(sizeof(struct omap_mcpdm), GFP_KERNEL); - if (!mcpdm) { - ret = -ENOMEM; - goto exit; - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res == NULL) { - dev_err(&pdev->dev, "no resource\n"); - goto err_resource; - } - - spin_lock_init(&mcpdm->lock); - mcpdm->free = 1; - mcpdm->io_base = ioremap(res->start, resource_size(res)); - if (!mcpdm->io_base) { - ret = -ENOMEM; - goto err_resource; - } - - mcpdm->irq = platform_get_irq(pdev, 0); - - mcpdm->clk = clk_get(&pdev->dev, "pdm_ck"); - if (IS_ERR(mcpdm->clk)) { - ret = PTR_ERR(mcpdm->clk); - dev_err(&pdev->dev, "unable to get pdm_ck: %d\n", ret); - goto err_clk; - } - - mcpdm->dev = &pdev->dev; - platform_set_drvdata(pdev, mcpdm); - - return 0; - -err_clk: - iounmap(mcpdm->io_base); -err_resource: - kfree(mcpdm); -exit: - return ret; -} - -int omap_mcpdm_remove(struct platform_device *pdev) -{ - struct omap_mcpdm *mcpdm_ptr = platform_get_drvdata(pdev); - - platform_set_drvdata(pdev, NULL); - - clk_put(mcpdm_ptr->clk); - - iounmap(mcpdm_ptr->io_base); - - mcpdm_ptr->clk = NULL; - mcpdm_ptr->free = 0; - mcpdm_ptr->dev = NULL; - - kfree(mcpdm_ptr); - - return 0; -} - diff --git a/sound/soc/omap/mcpdm.h b/sound/soc/omap/mcpdm.h deleted file mode 100644 index 20c20a8649f..00000000000 --- a/sound/soc/omap/mcpdm.h +++ /dev/null @@ -1,153 +0,0 @@ -/* - * mcpdm.h -- Defines for McPDM driver - * - * Author: Jorge Eduardo Candelaria <x0107209@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 - * - */ - -/* McPDM registers */ - -#define MCPDM_REVISION 0x00 -#define MCPDM_SYSCONFIG 0x10 -#define MCPDM_IRQSTATUS_RAW 0x24 -#define MCPDM_IRQSTATUS 0x28 -#define MCPDM_IRQENABLE_SET 0x2C -#define MCPDM_IRQENABLE_CLR 0x30 -#define MCPDM_IRQWAKE_EN 0x34 -#define MCPDM_DMAENABLE_SET 0x38 -#define MCPDM_DMAENABLE_CLR 0x3C -#define MCPDM_DMAWAKEEN 0x40 -#define MCPDM_CTRL 0x44 -#define MCPDM_DN_DATA 0x48 -#define MCPDM_UP_DATA 0x4C -#define MCPDM_FIFO_CTRL_DN 0x50 -#define MCPDM_FIFO_CTRL_UP 0x54 -#define MCPDM_DN_OFFSET 0x58 - -/* - * MCPDM_IRQ bit fields - * IRQSTATUS_RAW, IRQSTATUS, IRQENABLE_SET, IRQENABLE_CLR - */ - -#define MCPDM_DN_IRQ (1 << 0) -#define MCPDM_DN_IRQ_EMPTY (1 << 1) -#define MCPDM_DN_IRQ_ALMST_EMPTY (1 << 2) -#define MCPDM_DN_IRQ_FULL (1 << 3) - -#define MCPDM_UP_IRQ (1 << 8) -#define MCPDM_UP_IRQ_EMPTY (1 << 9) -#define MCPDM_UP_IRQ_ALMST_FULL (1 << 10) -#define MCPDM_UP_IRQ_FULL (1 << 11) - -#define MCPDM_DOWNLINK_IRQ_MASK 0x00F -#define MCPDM_UPLINK_IRQ_MASK 0xF00 - -/* - * MCPDM_DMAENABLE bit fields - */ - -#define DMA_DN_ENABLE 0x1 -#define DMA_UP_ENABLE 0x2 - -/* - * MCPDM_CTRL bit fields - */ - -#define PDM_UP1_EN 0x0001 -#define PDM_UP2_EN 0x0002 -#define PDM_UP3_EN 0x0004 -#define PDM_DN1_EN 0x0008 -#define PDM_DN2_EN 0x0010 -#define PDM_DN3_EN 0x0020 -#define PDM_DN4_EN 0x0040 -#define PDM_DN5_EN 0x0080 -#define PDMOUTFORMAT 0x0100 -#define CMD_INT 0x0200 -#define STATUS_INT 0x0400 -#define SW_UP_RST 0x0800 -#define SW_DN_RST 0x1000 -#define PDM_UP_MASK 0x007 -#define PDM_DN_MASK 0x0F8 -#define PDM_CMD_MASK 0x200 -#define PDM_STATUS_MASK 0x400 - - -#define PDMOUTFORMAT_LJUST (0 << 8) -#define PDMOUTFORMAT_RJUST (1 << 8) - -/* - * MCPDM_FIFO_CTRL bit fields - */ - -#define UP_THRES_MAX 0xF -#define DN_THRES_MAX 0xF - -/* - * MCPDM_DN_OFFSET bit fields - */ - -#define DN_OFST_RX1_EN 0x0001 -#define DN_OFST_RX2_EN 0x0100 - -#define DN_OFST_RX1 1 -#define DN_OFST_RX2 9 -#define DN_OFST_MAX 0x1F - -#define MCPDM_UPLINK 1 -#define MCPDM_DOWNLINK 2 - -struct omap_mcpdm_link { - int irq_mask; - int threshold; - int format; - int channels; -}; - -struct omap_mcpdm_platform_data { - unsigned long phys_base; - u16 irq; -}; - -struct omap_mcpdm { - struct device *dev; - unsigned long phys_base; - void __iomem *io_base; - u8 free; - int irq; - - spinlock_t lock; - struct omap_mcpdm_platform_data *pdata; - struct clk *clk; - struct omap_mcpdm_link *downlink; - struct omap_mcpdm_link *uplink; - struct completion irq_completion; - - int dn_channels; - int up_channels; -}; - -extern void omap_mcpdm_start(int stream); -extern void omap_mcpdm_stop(int stream); -extern int omap_mcpdm_capture_open(struct omap_mcpdm_link *uplink); -extern int omap_mcpdm_playback_open(struct omap_mcpdm_link *downlink); -extern int omap_mcpdm_capture_close(struct omap_mcpdm_link *uplink); -extern int omap_mcpdm_playback_close(struct omap_mcpdm_link *downlink); -extern int omap_mcpdm_request(void); -extern void omap_mcpdm_free(void); -extern int omap_mcpdm_set_offset(int offset1, int offset2); -int __devinit omap_mcpdm_probe(struct platform_device *pdev); -int omap_mcpdm_remove(struct platform_device *pdev); diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c index 62e292f4931..7e3c20c965c 100644 --- a/sound/soc/omap/n810.c +++ b/sound/soc/omap/n810.c @@ -115,25 +115,8 @@ static int n810_hw_params(struct snd_pcm_substream *substream, { 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 err; - /* Set codec DAI configuration */ - err = snd_soc_dai_set_fmt(codec_dai, - SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM); - if (err < 0) - return err; - - /* Set cpu DAI configuration */ - err = snd_soc_dai_set_fmt(cpu_dai, - SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM); - if (err < 0) - return err; - /* Set the codec system clock for DAC and ADC */ err = snd_soc_dai_set_sysclk(codec_dai, 0, 12000000, SND_SOC_CLOCK_IN); @@ -274,7 +257,6 @@ static int n810_aic33_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; struct snd_soc_dapm_context *dapm = &codec->dapm; - int err; /* Not connected */ snd_soc_dapm_nc_pin(dapm, "MONO_LOUT"); @@ -286,21 +268,6 @@ static int n810_aic33_init(struct snd_soc_pcm_runtime *rtd) snd_soc_dapm_nc_pin(dapm, "LINE2L"); snd_soc_dapm_nc_pin(dapm, "LINE2R"); - /* Add N810 specific controls */ - err = snd_soc_add_controls(codec, aic33_n810_controls, - ARRAY_SIZE(aic33_n810_controls)); - if (err < 0) - return err; - - /* Add N810 specific widgets */ - snd_soc_dapm_new_controls(dapm, aic33_dapm_widgets, - ARRAY_SIZE(aic33_dapm_widgets)); - - /* Set up N810 specific audio path audio_map */ - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - - snd_soc_dapm_sync(dapm); - return 0; } @@ -312,6 +279,8 @@ static struct snd_soc_dai_link n810_dai = { .platform_name = "omap-pcm-audio", .codec_name = "tlv320aic3x-codec.2-0018", .codec_dai_name = "tlv320aic3x-hifi", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBM_CFM, .init = n810_aic33_init, .ops = &n810_ops, }; @@ -321,6 +290,13 @@ static struct snd_soc_card snd_soc_n810 = { .name = "N810", .dai_link = &n810_dai, .num_links = 1, + + .controls = aic33_n810_controls, + .num_controls = ARRAY_SIZE(aic33_n810_controls), + .dapm_widgets = aic33_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(aic33_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static struct platform_device *n810_snd_device; diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index 478d6077845..4314647e735 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c @@ -317,6 +317,10 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, return 0; } + regs->rcr2 &= ~(RPHASE | RFRLEN2(0x7f) | RWDLEN2(7)); + regs->xcr2 &= ~(RPHASE | XFRLEN2(0x7f) | XWDLEN2(7)); + regs->rcr1 &= ~(RFRLEN1(0x7f) | RWDLEN1(7)); + regs->xcr1 &= ~(XFRLEN1(0x7f) | XWDLEN1(7)); format = mcbsp_data->fmt & SND_SOC_DAIFMT_FORMAT_MASK; wpf = channels = params_channels(params); if (channels == 2 && (format == SND_SOC_DAIFMT_I2S || @@ -369,6 +373,8 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, framesize = wlen * channels; /* Set FS period and length in terms of bit clock periods */ + regs->srgr2 &= ~FPER(0xfff); + regs->srgr1 &= ~FWID(0xff); switch (format) { case SND_SOC_DAIFMT_I2S: case SND_SOC_DAIFMT_LEFT_J: @@ -398,7 +404,7 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai, { struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai); struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; - unsigned int temp_fmt = fmt; + bool inv_fs = false; if (mcbsp_data->configured) return 0; @@ -430,21 +436,21 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai, regs->xcr2 |= XDATDLY(0); regs->spcr1 |= RJUST(2); /* Invert FS polarity configuration */ - temp_fmt ^= SND_SOC_DAIFMT_NB_IF; + inv_fs = true; break; case SND_SOC_DAIFMT_DSP_A: /* 1-bit data delay */ regs->rcr2 |= RDATDLY(1); regs->xcr2 |= XDATDLY(1); /* Invert FS polarity configuration */ - temp_fmt ^= SND_SOC_DAIFMT_NB_IF; + inv_fs = true; break; case SND_SOC_DAIFMT_DSP_B: /* 0-bit data delay */ regs->rcr2 |= RDATDLY(0); regs->xcr2 |= XDATDLY(0); /* Invert FS polarity configuration */ - temp_fmt ^= SND_SOC_DAIFMT_NB_IF; + inv_fs = true; break; default: /* Unsupported data format */ @@ -468,7 +474,7 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai, } /* Set bit clock (CLKX/CLKR) and FS polarities */ - switch (temp_fmt & SND_SOC_DAIFMT_INV_MASK) { + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_NB_NF: /* * Normal BCLK + FS. @@ -489,6 +495,8 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai, default: return -EINVAL; } + if (inv_fs == true) + regs->pcr0 ^= FSXP | FSRP; return 0; } @@ -503,6 +511,7 @@ static int omap_mcbsp_dai_set_clkdiv(struct snd_soc_dai *cpu_dai, return -ENODEV; mcbsp_data->clk_div = div; + regs->srgr1 &= ~CLKGDV(0xff); regs->srgr1 |= CLKGDV(div - 1); return 0; @@ -516,11 +525,12 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; int err = 0; - if (mcbsp_data->active) + if (mcbsp_data->active) { if (freq == mcbsp_data->in_freq) return 0; else return -EBUSY; + } /* The McBSP signal muxing functions are only available on McBSP1 */ if (clk_id == OMAP_MCBSP_CLKR_SRC_CLKR || @@ -531,6 +541,8 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, return -EINVAL; mcbsp_data->in_freq = freq; + regs->srgr2 &= ~CLKSM; + regs->pcr0 &= ~SCLKME; switch (clk_id) { case OMAP_MCBSP_SYSCLK_CLK: @@ -605,8 +617,7 @@ static int mcbsp_dai_probe(struct snd_soc_dai *dai) return 0; } -static struct snd_soc_dai_driver omap_mcbsp_dai = -{ +static struct snd_soc_dai_driver omap_mcbsp_dai = { .probe = mcbsp_dai_probe, .playback = { .channels_min = 1, diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c index bed09c27e44..41d17067cc7 100644 --- a/sound/soc/omap/omap-mcpdm.c +++ b/sound/soc/omap/omap-mcpdm.c @@ -1,11 +1,12 @@ /* * omap-mcpdm.c -- OMAP ALSA SoC DAI driver using McPDM port * - * Copyright (C) 2009 Texas Instruments + * Copyright (C) 2009 - 2011 Texas Instruments * - * Author: Misael Lopez Cruz <x0052729@ti.com> + * Author: Misael Lopez Cruz <misael.lopez@ti.com> * Contact: Jorge Eduardo Candelaria <x0107209@ti.com> * Margarita Olaya <magi.olaya@ti.com> + * Peter Ujfalusi <peter.ujfalusi@ti.com> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -25,41 +26,42 @@ #include <linux/init.h> #include <linux/module.h> -#include <linux/device.h> +#include <linux/platform_device.h> +#include <linux/interrupt.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/irq.h> +#include <linux/slab.h> +#include <linux/pm_runtime.h> + #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> -#include <sound/initval.h> #include <sound/soc.h> #include <plat/dma.h> -#include <plat/mcbsp.h> -#include "mcpdm.h" +#include <plat/omap_hwmod.h> +#include "omap-mcpdm.h" #include "omap-pcm.h" -struct omap_mcpdm_data { - struct omap_mcpdm_link *links; - int active; -}; +struct omap_mcpdm { + struct device *dev; + unsigned long phys_base; + void __iomem *io_base; + int irq; -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, - }, -}; + struct mutex mutex; + + /* channel data */ + u32 dn_channels; + u32 up_channels; + + /* McPDM FIFO thresholds */ + u32 dn_threshold; + u32 up_threshold; -static struct omap_mcpdm_data mcpdm_data = { - .links = omap_mcpdm_links, - .active = 0, + /* McPDM dn offsets for rx1, and 2 channels */ + u32 dn_rx_offset; }; /* @@ -71,88 +73,259 @@ static struct omap_pcm_dma_data omap_mcpdm_dai_dma_params[] = { .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, + .port_addr = OMAP44XX_MCPDM_L3_BASE + MCPDM_REG_DN_DATA, }, { .name = "Audio capture", .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, + .port_addr = OMAP44XX_MCPDM_L3_BASE + MCPDM_REG_UP_DATA, }, }; -static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) +static inline void omap_mcpdm_write(struct omap_mcpdm *mcpdm, u16 reg, u32 val) { - int err = 0; + __raw_writel(val, mcpdm->io_base + reg); +} - if (!dai->active) - err = omap_mcpdm_request(); +static inline int omap_mcpdm_read(struct omap_mcpdm *mcpdm, u16 reg) +{ + return __raw_readl(mcpdm->io_base + reg); +} - return err; +#ifdef DEBUG +static void omap_mcpdm_reg_dump(struct omap_mcpdm *mcpdm) +{ + dev_dbg(mcpdm->dev, "***********************\n"); + dev_dbg(mcpdm->dev, "IRQSTATUS_RAW: 0x%04x\n", + omap_mcpdm_read(mcpdm, MCPDM_REG_IRQSTATUS_RAW)); + dev_dbg(mcpdm->dev, "IRQSTATUS: 0x%04x\n", + omap_mcpdm_read(mcpdm, MCPDM_REG_IRQSTATUS)); + dev_dbg(mcpdm->dev, "IRQENABLE_SET: 0x%04x\n", + omap_mcpdm_read(mcpdm, MCPDM_REG_IRQENABLE_SET)); + dev_dbg(mcpdm->dev, "IRQENABLE_CLR: 0x%04x\n", + omap_mcpdm_read(mcpdm, MCPDM_REG_IRQENABLE_CLR)); + dev_dbg(mcpdm->dev, "IRQWAKE_EN: 0x%04x\n", + omap_mcpdm_read(mcpdm, MCPDM_REG_IRQWAKE_EN)); + dev_dbg(mcpdm->dev, "DMAENABLE_SET: 0x%04x\n", + omap_mcpdm_read(mcpdm, MCPDM_REG_DMAENABLE_SET)); + dev_dbg(mcpdm->dev, "DMAENABLE_CLR: 0x%04x\n", + omap_mcpdm_read(mcpdm, MCPDM_REG_DMAENABLE_CLR)); + dev_dbg(mcpdm->dev, "DMAWAKEEN: 0x%04x\n", + omap_mcpdm_read(mcpdm, MCPDM_REG_DMAWAKEEN)); + dev_dbg(mcpdm->dev, "CTRL: 0x%04x\n", + omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL)); + dev_dbg(mcpdm->dev, "DN_DATA: 0x%04x\n", + omap_mcpdm_read(mcpdm, MCPDM_REG_DN_DATA)); + dev_dbg(mcpdm->dev, "UP_DATA: 0x%04x\n", + omap_mcpdm_read(mcpdm, MCPDM_REG_UP_DATA)); + dev_dbg(mcpdm->dev, "FIFO_CTRL_DN: 0x%04x\n", + omap_mcpdm_read(mcpdm, MCPDM_REG_FIFO_CTRL_DN)); + dev_dbg(mcpdm->dev, "FIFO_CTRL_UP: 0x%04x\n", + omap_mcpdm_read(mcpdm, MCPDM_REG_FIFO_CTRL_UP)); + dev_dbg(mcpdm->dev, "***********************\n"); } +#else +static void omap_mcpdm_reg_dump(struct omap_mcpdm *mcpdm) {} +#endif -static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) +/* + * Enables the transfer through the PDM interface to/from the Phoenix + * codec by enabling the corresponding UP or DN channels. + */ +static void omap_mcpdm_start(struct omap_mcpdm *mcpdm) +{ + u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL); + + ctrl |= (MCPDM_SW_DN_RST | MCPDM_SW_UP_RST); + omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl); + + ctrl |= mcpdm->dn_channels | mcpdm->up_channels; + omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl); + + ctrl &= ~(MCPDM_SW_DN_RST | MCPDM_SW_UP_RST); + omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl); +} + +/* + * Disables the transfer through the PDM interface to/from the Phoenix + * codec by disabling the corresponding UP or DN channels. + */ +static void omap_mcpdm_stop(struct omap_mcpdm *mcpdm) +{ + u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL); + + ctrl |= (MCPDM_SW_DN_RST | MCPDM_SW_UP_RST); + omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl); + + ctrl &= ~(mcpdm->dn_channels | mcpdm->up_channels); + omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl); + + ctrl &= ~(MCPDM_SW_DN_RST | MCPDM_SW_UP_RST); + omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl); + +} + +/* + * Is the physical McPDM interface active. + */ +static inline int omap_mcpdm_active(struct omap_mcpdm *mcpdm) +{ + return omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL) & + (MCPDM_PDM_DN_MASK | MCPDM_PDM_UP_MASK); +} + +/* + * Configures McPDM uplink, and downlink for audio. + * This function should be called before omap_mcpdm_start. + */ +static void omap_mcpdm_open_streams(struct omap_mcpdm *mcpdm) +{ + omap_mcpdm_write(mcpdm, MCPDM_REG_IRQENABLE_SET, + MCPDM_DN_IRQ_EMPTY | MCPDM_DN_IRQ_FULL | + MCPDM_UP_IRQ_EMPTY | MCPDM_UP_IRQ_FULL); + + /* Enable DN RX1/2 offset cancellation feature, if configured */ + if (mcpdm->dn_rx_offset) { + u32 dn_offset = mcpdm->dn_rx_offset; + + omap_mcpdm_write(mcpdm, MCPDM_REG_DN_OFFSET, dn_offset); + dn_offset |= (MCPDM_DN_OFST_RX1_EN | MCPDM_DN_OFST_RX2_EN); + omap_mcpdm_write(mcpdm, MCPDM_REG_DN_OFFSET, dn_offset); + } + + omap_mcpdm_write(mcpdm, MCPDM_REG_FIFO_CTRL_DN, mcpdm->dn_threshold); + omap_mcpdm_write(mcpdm, MCPDM_REG_FIFO_CTRL_UP, mcpdm->up_threshold); + + omap_mcpdm_write(mcpdm, MCPDM_REG_DMAENABLE_SET, + MCPDM_DMA_DN_ENABLE | MCPDM_DMA_UP_ENABLE); +} + +/* + * Cleans McPDM uplink, and downlink configuration. + * This function should be called when the stream is closed. + */ +static void omap_mcpdm_close_streams(struct omap_mcpdm *mcpdm) +{ + /* Disable irq request generation for downlink */ + omap_mcpdm_write(mcpdm, MCPDM_REG_IRQENABLE_CLR, + MCPDM_DN_IRQ_EMPTY | MCPDM_DN_IRQ_FULL); + + /* Disable DMA request generation for downlink */ + omap_mcpdm_write(mcpdm, MCPDM_REG_DMAENABLE_CLR, MCPDM_DMA_DN_ENABLE); + + /* Disable irq request generation for uplink */ + omap_mcpdm_write(mcpdm, MCPDM_REG_IRQENABLE_CLR, + MCPDM_UP_IRQ_EMPTY | MCPDM_UP_IRQ_FULL); + + /* Disable DMA request generation for uplink */ + omap_mcpdm_write(mcpdm, MCPDM_REG_DMAENABLE_CLR, MCPDM_DMA_UP_ENABLE); + + /* Disable RX1/2 offset cancellation */ + if (mcpdm->dn_rx_offset) + omap_mcpdm_write(mcpdm, MCPDM_REG_DN_OFFSET, 0); +} + +static irqreturn_t omap_mcpdm_irq_handler(int irq, void *dev_id) +{ + struct omap_mcpdm *mcpdm = dev_id; + int irq_status; + + irq_status = omap_mcpdm_read(mcpdm, MCPDM_REG_IRQSTATUS); + + /* Acknowledge irq event */ + omap_mcpdm_write(mcpdm, MCPDM_REG_IRQSTATUS, irq_status); + + if (irq_status & MCPDM_DN_IRQ_FULL) + dev_dbg(mcpdm->dev, "DN (playback) FIFO Full\n"); + + if (irq_status & MCPDM_DN_IRQ_EMPTY) + dev_dbg(mcpdm->dev, "DN (playback) FIFO Empty\n"); + + if (irq_status & MCPDM_DN_IRQ) + dev_dbg(mcpdm->dev, "DN (playback) write request\n"); + + if (irq_status & MCPDM_UP_IRQ_FULL) + dev_dbg(mcpdm->dev, "UP (capture) FIFO Full\n"); + + if (irq_status & MCPDM_UP_IRQ_EMPTY) + dev_dbg(mcpdm->dev, "UP (capture) FIFO Empty\n"); + + if (irq_status & MCPDM_UP_IRQ) + dev_dbg(mcpdm->dev, "UP (capture) write request\n"); + + return IRQ_HANDLED; +} + +static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) { - if (!dai->active) - omap_mcpdm_free(); + struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai); + + mutex_lock(&mcpdm->mutex); + + if (!dai->active) { + pm_runtime_get_sync(mcpdm->dev); + + /* Enable watch dog for ES above ES 1.0 to avoid saturation */ + if (omap_rev() != OMAP4430_REV_ES1_0) { + u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL); + + omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, + ctrl | MCPDM_WD_EN); + } + omap_mcpdm_open_streams(mcpdm); + } + + mutex_unlock(&mcpdm->mutex); + + return 0; } -static int omap_mcpdm_dai_trigger(struct snd_pcm_substream *substream, int cmd, +static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct omap_mcpdm_data *mcpdm_priv = snd_soc_dai_get_drvdata(dai); - 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; + struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai); - 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; + mutex_lock(&mcpdm->mutex); + + if (!dai->active) { + if (omap_mcpdm_active(mcpdm)) { + omap_mcpdm_stop(mcpdm); + omap_mcpdm_close_streams(mcpdm); + } + + if (!omap_mcpdm_active(mcpdm)) + pm_runtime_put_sync(mcpdm->dev); } - return err; + mutex_unlock(&mcpdm->mutex); } static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct omap_mcpdm_data *mcpdm_priv = snd_soc_dai_get_drvdata(dai); - struct omap_mcpdm_link *mcpdm_links = mcpdm_priv->links; + struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai); int stream = substream->stream; - int channels, err, link_mask = 0; - - snd_soc_dai_set_dma_data(dai, substream, - &omap_mcpdm_dai_dma_params[stream]); + struct omap_pcm_dma_data *dma_data; + int channels; + int link_mask = 0; channels = params_channels(params); switch (channels) { + case 5: + if (stream == SNDRV_PCM_STREAM_CAPTURE) + /* up to 3 channels for capture */ + return -EINVAL; + link_mask |= 1 << 4; case 4: if (stream == SNDRV_PCM_STREAM_CAPTURE) - /* up to 2 channels for capture */ + /* up to 3 channels for capture */ return -EINVAL; link_mask |= 1 << 3; case 3: - if (stream == SNDRV_PCM_STREAM_CAPTURE) - /* up to 2 channels for capture */ - return -EINVAL; link_mask |= 1 << 2; case 2: link_mask |= 1 << 1; @@ -164,95 +337,187 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } + dma_data = &omap_mcpdm_dai_dma_params[stream]; + + /* Configure McPDM channels, and DMA packet size */ if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - mcpdm_links[stream].channels = link_mask << 3; - err = omap_mcpdm_playback_open(&mcpdm_links[stream]); + mcpdm->dn_channels = link_mask << 3; + dma_data->packet_size = + (MCPDM_DN_THRES_MAX - mcpdm->dn_threshold) * channels; } else { - mcpdm_links[stream].channels = link_mask << 0; - err = omap_mcpdm_capture_open(&mcpdm_links[stream]); + mcpdm->up_channels = link_mask << 0; + dma_data->packet_size = mcpdm->up_threshold * channels; } - return err; + snd_soc_dai_set_dma_data(dai, substream, dma_data); + + return 0; } -static int omap_mcpdm_dai_hw_free(struct snd_pcm_substream *substream, +static int omap_mcpdm_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct omap_mcpdm_data *mcpdm_priv = snd_soc_dai_get_drvdata(dai); - struct omap_mcpdm_link *mcpdm_links = mcpdm_priv->links; - int stream = substream->stream; - int err; + struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - err = omap_mcpdm_playback_close(&mcpdm_links[stream]); - else - err = omap_mcpdm_capture_close(&mcpdm_links[stream]); + if (!omap_mcpdm_active(mcpdm)) { + omap_mcpdm_start(mcpdm); + omap_mcpdm_reg_dump(mcpdm); + } - return err; + return 0; } 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, + .prepare = omap_mcpdm_prepare, }; -#define OMAP_MCPDM_RATES (SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) -#define OMAP_MCPDM_FORMATS (SNDRV_PCM_FMTBIT_S32_LE) +static int omap_mcpdm_probe(struct snd_soc_dai *dai) +{ + struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai); + int ret; -static int omap_mcpdm_dai_probe(struct snd_soc_dai *dai) + pm_runtime_enable(mcpdm->dev); + + /* Disable lines while request is ongoing */ + pm_runtime_get_sync(mcpdm->dev); + omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, 0x00); + + ret = request_irq(mcpdm->irq, omap_mcpdm_irq_handler, + 0, "McPDM", (void *)mcpdm); + + pm_runtime_put_sync(mcpdm->dev); + + if (ret) { + dev_err(mcpdm->dev, "Request for IRQ failed\n"); + pm_runtime_disable(mcpdm->dev); + } + + /* Configure McPDM threshold values */ + mcpdm->dn_threshold = 2; + mcpdm->up_threshold = MCPDM_UP_THRES_MAX - 3; + return ret; +} + +static int omap_mcpdm_remove(struct snd_soc_dai *dai) { - snd_soc_dai_set_drvdata(dai, &mcpdm_data); + struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai); + + free_irq(mcpdm->irq, (void *)mcpdm); + pm_runtime_disable(mcpdm->dev); + return 0; } +#define OMAP_MCPDM_RATES (SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) +#define OMAP_MCPDM_FORMATS SNDRV_PCM_FMTBIT_S32_LE + static struct snd_soc_dai_driver omap_mcpdm_dai = { - .probe = omap_mcpdm_dai_probe, + .probe = omap_mcpdm_probe, + .remove = omap_mcpdm_remove, + .probe_order = SND_SOC_COMP_ORDER_LATE, + .remove_order = SND_SOC_COMP_ORDER_EARLY, .playback = { .channels_min = 1, - .channels_max = 4, + .channels_max = 5, .rates = OMAP_MCPDM_RATES, .formats = OMAP_MCPDM_FORMATS, }, .capture = { .channels_min = 1, - .channels_max = 2, + .channels_max = 3, .rates = OMAP_MCPDM_RATES, .formats = OMAP_MCPDM_FORMATS, }, .ops = &omap_mcpdm_dai_ops, }; +void omap_mcpdm_configure_dn_offsets(struct snd_soc_pcm_runtime *rtd, + u8 rx1, u8 rx2) +{ + struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(rtd->cpu_dai); + + mcpdm->dn_rx_offset = MCPDM_DNOFST_RX1(rx1) | MCPDM_DNOFST_RX2(rx2); +} +EXPORT_SYMBOL_GPL(omap_mcpdm_configure_dn_offsets); + static __devinit int asoc_mcpdm_probe(struct platform_device *pdev) { - int ret; + struct omap_mcpdm *mcpdm; + struct resource *res; + int ret = 0; + + mcpdm = kzalloc(sizeof(struct omap_mcpdm), GFP_KERNEL); + if (!mcpdm) + return -ENOMEM; + + platform_set_drvdata(pdev, mcpdm); + + mutex_init(&mcpdm->mutex); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + dev_err(&pdev->dev, "no resource\n"); + goto err_res; + } + + if (!request_mem_region(res->start, resource_size(res), "McPDM")) { + ret = -EBUSY; + goto err_res; + } + + mcpdm->io_base = ioremap(res->start, resource_size(res)); + if (!mcpdm->io_base) { + ret = -ENOMEM; + goto err_iomap; + } + + mcpdm->irq = platform_get_irq(pdev, 0); + if (mcpdm->irq < 0) { + ret = mcpdm->irq; + goto err_irq; + } + + mcpdm->dev = &pdev->dev; - ret = omap_mcpdm_probe(pdev); - if (ret < 0) - return ret; ret = snd_soc_register_dai(&pdev->dev, &omap_mcpdm_dai); - if (ret < 0) - omap_mcpdm_remove(pdev); + if (!ret) + return 0; + +err_irq: + iounmap(mcpdm->io_base); +err_iomap: + release_mem_region(res->start, resource_size(res)); +err_res: + kfree(mcpdm); return ret; } static int __devexit asoc_mcpdm_remove(struct platform_device *pdev) { + struct omap_mcpdm *mcpdm = platform_get_drvdata(pdev); + struct resource *res; + snd_soc_unregister_dai(&pdev->dev); - omap_mcpdm_remove(pdev); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + iounmap(mcpdm->io_base); + release_mem_region(res->start, resource_size(res)); + + kfree(mcpdm); return 0; } static struct platform_driver asoc_mcpdm_driver = { .driver = { - .name = "omap-mcpdm-dai", - .owner = THIS_MODULE, + .name = "omap-mcpdm", + .owner = THIS_MODULE, }, - .probe = asoc_mcpdm_probe, - .remove = __devexit_p(asoc_mcpdm_remove), + .probe = asoc_mcpdm_probe, + .remove = __devexit_p(asoc_mcpdm_remove), }; static int __init snd_omap_mcpdm_init(void) @@ -267,6 +532,6 @@ static void __exit snd_omap_mcpdm_exit(void) } module_exit(snd_omap_mcpdm_exit); -MODULE_AUTHOR("Misael Lopez Cruz <x0052729@ti.com>"); +MODULE_AUTHOR("Misael Lopez Cruz <misael.lopez@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 00000000000..de8cf26595b --- /dev/null +++ b/sound/soc/omap/omap-mcpdm.h @@ -0,0 +1,107 @@ +/* + * omap-mcpdm.h + * + * Copyright (C) 2009 - 2011 Texas Instruments + * + * Contact: Misael Lopez Cruz <misael.lopez@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 MCPDM_REG_REVISION 0x00 +#define MCPDM_REG_SYSCONFIG 0x10 +#define MCPDM_REG_IRQSTATUS_RAW 0x24 +#define MCPDM_REG_IRQSTATUS 0x28 +#define MCPDM_REG_IRQENABLE_SET 0x2C +#define MCPDM_REG_IRQENABLE_CLR 0x30 +#define MCPDM_REG_IRQWAKE_EN 0x34 +#define MCPDM_REG_DMAENABLE_SET 0x38 +#define MCPDM_REG_DMAENABLE_CLR 0x3C +#define MCPDM_REG_DMAWAKEEN 0x40 +#define MCPDM_REG_CTRL 0x44 +#define MCPDM_REG_DN_DATA 0x48 +#define MCPDM_REG_UP_DATA 0x4C +#define MCPDM_REG_FIFO_CTRL_DN 0x50 +#define MCPDM_REG_FIFO_CTRL_UP 0x54 +#define MCPDM_REG_DN_OFFSET 0x58 + +/* + * MCPDM_IRQ bit fields + * IRQSTATUS_RAW, IRQSTATUS, IRQENABLE_SET, IRQENABLE_CLR + */ + +#define MCPDM_DN_IRQ (1 << 0) +#define MCPDM_DN_IRQ_EMPTY (1 << 1) +#define MCPDM_DN_IRQ_ALMST_EMPTY (1 << 2) +#define MCPDM_DN_IRQ_FULL (1 << 3) + +#define MCPDM_UP_IRQ (1 << 8) +#define MCPDM_UP_IRQ_EMPTY (1 << 9) +#define MCPDM_UP_IRQ_ALMST_FULL (1 << 10) +#define MCPDM_UP_IRQ_FULL (1 << 11) + +#define MCPDM_DOWNLINK_IRQ_MASK 0x00F +#define MCPDM_UPLINK_IRQ_MASK 0xF00 + +/* + * MCPDM_DMAENABLE bit fields + */ + +#define MCPDM_DMA_DN_ENABLE (1 << 0) +#define MCPDM_DMA_UP_ENABLE (1 << 1) + +/* + * MCPDM_CTRL bit fields + */ + +#define MCPDM_PDM_UPLINK_EN(x) (1 << (x - 1)) /* ch1 is at bit 0 */ +#define MCPDM_PDM_DOWNLINK_EN(x) (1 << (x + 2)) /* ch1 is at bit 3 */ +#define MCPDM_PDMOUTFORMAT (1 << 8) +#define MCPDM_CMD_INT (1 << 9) +#define MCPDM_STATUS_INT (1 << 10) +#define MCPDM_SW_UP_RST (1 << 11) +#define MCPDM_SW_DN_RST (1 << 12) +#define MCPDM_WD_EN (1 << 14) +#define MCPDM_PDM_UP_MASK 0x7 +#define MCPDM_PDM_DN_MASK (0x1f << 3) + + +#define MCPDM_PDMOUTFORMAT_LJUST (0 << 8) +#define MCPDM_PDMOUTFORMAT_RJUST (1 << 8) + +/* + * MCPDM_FIFO_CTRL bit fields + */ + +#define MCPDM_UP_THRES_MAX 0xF +#define MCPDM_DN_THRES_MAX 0xF + +/* + * MCPDM_DN_OFFSET bit fields + */ + +#define MCPDM_DN_OFST_RX1_EN (1 << 0) +#define MCPDM_DNOFST_RX1(x) ((x & 0x1f) << 1) +#define MCPDM_DN_OFST_RX2_EN (1 << 8) +#define MCPDM_DNOFST_RX2(x) ((x & 0x1f) << 9) + +void omap_mcpdm_configure_dn_offsets(struct snd_soc_pcm_runtime *rtd, + u8 rx1, u8 rx2); + +#endif /* End of __OMAP_MCPDM_H__ */ diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c index 9b5c88ac35b..5e37ec915de 100644 --- a/sound/soc/omap/omap-pcm.c +++ b/sound/soc/omap/omap-pcm.c @@ -198,6 +198,14 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream) OMAP_DMA_LAST_IRQ | OMAP_DMA_BLOCK_IRQ); else if (!substream->runtime->no_period_wakeup) omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ); + else { + /* + * No period wakeup: + * we need to disable BLOCK_IRQ, which is enabled by the omap + * dma core at request dma time. + */ + omap_disable_dma_irq(prtd->dma_ch, OMAP_DMA_BLOCK_IRQ); + } if (!(cpu_class_is_omap1())) { omap_set_dma_src_burst_mode(prtd->dma_ch, diff --git a/sound/soc/omap/omap3evm.c b/sound/soc/omap/omap3evm.c index 0daa0446983..bf9ae2a6f90 100644 --- a/sound/soc/omap/omap3evm.c +++ b/sound/soc/omap/omap3evm.c @@ -36,29 +36,8 @@ static int omap3evm_hw_params(struct snd_pcm_substream *substream, { 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; - /* 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); @@ -82,6 +61,8 @@ static struct snd_soc_dai_link omap3evm_dai = { .codec_dai_name = "twl4030-hifi", .platform_name = "omap-pcm-audio", .codec_name = "twl4030-codec", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBM_CFM, .ops = &omap3evm_ops, }; diff --git a/sound/soc/omap/omap3pandora.c b/sound/soc/omap/omap3pandora.c index 8047c521e31..30a75b406ae 100644 --- a/sound/soc/omap/omap3pandora.c +++ b/sound/soc/omap/omap3pandora.c @@ -48,24 +48,8 @@ static int omap3pandora_hw_params(struct snd_pcm_substream *substream, 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 fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS; 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); @@ -189,10 +173,8 @@ static int omap3pandora_out_init(struct snd_soc_pcm_runtime *rtd) if (ret < 0) return ret; - snd_soc_dapm_add_routes(dapm, omap3pandora_out_map, + return snd_soc_dapm_add_routes(dapm, omap3pandora_out_map, ARRAY_SIZE(omap3pandora_out_map)); - - return snd_soc_dapm_sync(dapm); } static int omap3pandora_in_init(struct snd_soc_pcm_runtime *rtd) @@ -212,10 +194,8 @@ static int omap3pandora_in_init(struct snd_soc_pcm_runtime *rtd) if (ret < 0) return ret; - snd_soc_dapm_add_routes(dapm, omap3pandora_in_map, + return snd_soc_dapm_add_routes(dapm, omap3pandora_in_map, ARRAY_SIZE(omap3pandora_in_map)); - - return snd_soc_dapm_sync(dapm); } static struct snd_soc_ops omap3pandora_ops = { @@ -231,6 +211,8 @@ static struct snd_soc_dai_link omap3pandora_dai[] = { .codec_dai_name = "twl4030-hifi", .platform_name = "omap-pcm-audio", .codec_name = "twl4030-codec", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, .ops = &omap3pandora_ops, .init = omap3pandora_out_init, }, { @@ -240,6 +222,8 @@ static struct snd_soc_dai_link omap3pandora_dai[] = { .codec_dai_name = "twl4030-hifi", .platform_name = "omap-pcm-audio", .codec_name = "twl4030-codec", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, .ops = &omap3pandora_ops, .init = omap3pandora_in_init, } diff --git a/sound/soc/omap/osk5912.c b/sound/soc/omap/osk5912.c index 7e75e775fb4..db91ccaf6c9 100644 --- a/sound/soc/omap/osk5912.c +++ b/sound/soc/omap/osk5912.c @@ -55,29 +55,8 @@ static int osk_hw_params(struct snd_pcm_substream *substream, { 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 err; - /* Set codec DAI configuration */ - err = snd_soc_dai_set_fmt(codec_dai, - SND_SOC_DAIFMT_DSP_B | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM); - if (err < 0) { - printk(KERN_ERR "can't set codec DAI configuration\n"); - return err; - } - - /* Set cpu DAI configuration */ - err = snd_soc_dai_set_fmt(cpu_dai, - SND_SOC_DAIFMT_DSP_B | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM); - if (err < 0) { - printk(KERN_ERR "can't set cpu DAI configuration\n"); - return err; - } - /* Set the codec system clock for DAC and ADC */ err = snd_soc_dai_set_sysclk(codec_dai, 0, CODEC_CLOCK, SND_SOC_CLOCK_IN); @@ -112,27 +91,6 @@ static const struct snd_soc_dapm_route audio_map[] = { {"MICIN", NULL, "Mic Jack"}, }; -static int osk_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - - /* Add osk5912 specific widgets */ - snd_soc_dapm_new_controls(dapm, tlv320aic23_dapm_widgets, - ARRAY_SIZE(tlv320aic23_dapm_widgets)); - - /* Set up osk5912 specific audio path audio_map */ - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - - snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); - snd_soc_dapm_enable_pin(dapm, "Line In"); - snd_soc_dapm_enable_pin(dapm, "Mic Jack"); - - snd_soc_dapm_sync(dapm); - - return 0; -} - /* Digital audio interface glue - connects codec <--> CPU */ static struct snd_soc_dai_link osk_dai = { .name = "TLV320AIC23", @@ -141,7 +99,8 @@ static struct snd_soc_dai_link osk_dai = { .codec_dai_name = "tlv320aic23-hifi", .platform_name = "omap-pcm-audio", .codec_name = "tlv320aic23-codec", - .init = osk_tlv320aic23_init, + .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBM_CFM, .ops = &osk_ops, }; @@ -150,6 +109,11 @@ static struct snd_soc_card snd_soc_card_osk = { .name = "OSK5912", .dai_link = &osk_dai, .num_links = 1, + + .dapm_widgets = tlv320aic23_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(tlv320aic23_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static struct platform_device *osk_snd_device; diff --git a/sound/soc/omap/overo.c b/sound/soc/omap/overo.c index bbcf380bfb5..739efe9e327 100644 --- a/sound/soc/omap/overo.c +++ b/sound/soc/omap/overo.c @@ -38,29 +38,8 @@ static int overo_hw_params(struct snd_pcm_substream *substream, { 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; - /* 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); @@ -84,6 +63,8 @@ static struct snd_soc_dai_link overo_dai = { .codec_dai_name = "twl4030-hifi", .platform_name = "omap-pcm-audio", .codec_name = "twl4030-codec", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBM_CFM, .ops = &overo_ops, }; diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c index 893300a53ba..a56842380c7 100644 --- a/sound/soc/omap/rx51.c +++ b/sound/soc/omap/rx51.c @@ -115,24 +115,6 @@ static int rx51_hw_params(struct snd_pcm_substream *substream, { 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 err; - - /* Set codec DAI configuration */ - err = snd_soc_dai_set_fmt(codec_dai, - SND_SOC_DAIFMT_DSP_A | - SND_SOC_DAIFMT_IB_NF | - SND_SOC_DAIFMT_CBM_CFM); - if (err < 0) - return err; - - /* Set cpu DAI configuration */ - err = snd_soc_dai_set_fmt(cpu_dai, - SND_SOC_DAIFMT_DSP_A | - SND_SOC_DAIFMT_IB_NF | - SND_SOC_DAIFMT_CBM_CFM); - if (err < 0) - return err; /* Set the codec system clock for DAC and ADC */ return snd_soc_dai_set_sysclk(codec_dai, 0, 19200000, @@ -335,8 +317,6 @@ static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd) if (err < 0) return err; - snd_soc_dapm_sync(dapm); - /* AV jack detection */ err = snd_soc_jack_new(codec, "AV Jack", SND_JACK_HEADSET | SND_JACK_VIDEOOUT, @@ -377,6 +357,8 @@ static struct snd_soc_dai_link rx51_dai[] = { .codec_dai_name = "tlv320aic3x-hifi", .platform_name = "omap-pcm-audio", .codec_name = "tlv320aic3x-codec.2-0018", + .dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF | + SND_SOC_DAIFMT_CBM_CFM, .init = rx51_aic34_init, .ops = &rx51_ops, }, diff --git a/sound/soc/omap/sdp3430.c b/sound/soc/omap/sdp3430.c index 9f6a758029d..4f1969de91a 100644 --- a/sound/soc/omap/sdp3430.c +++ b/sound/soc/omap/sdp3430.c @@ -53,29 +53,8 @@ static int sdp3430_hw_params(struct snd_pcm_substream *substream, { 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; - /* 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); @@ -91,49 +70,6 @@ static struct snd_soc_ops sdp3430_ops = { .hw_params = sdp3430_hw_params, }; -static int sdp3430_hw_voice_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; - - /* Set codec DAI configuration */ - ret = snd_soc_dai_set_fmt(codec_dai, - SND_SOC_DAIFMT_DSP_A | - SND_SOC_DAIFMT_IB_NF | - SND_SOC_DAIFMT_CBM_CFM); - if (ret) { - 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_DSP_A | - SND_SOC_DAIFMT_IB_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_voice_ops = { - .hw_params = sdp3430_hw_voice_params, -}; - /* Headset jack */ static struct snd_soc_jack hs_jack; @@ -193,15 +129,6 @@ static int sdp3430_twl4030_init(struct snd_soc_pcm_runtime *rtd) struct snd_soc_dapm_context *dapm = &codec->dapm; int ret; - /* Add SDP3430 specific widgets */ - ret = snd_soc_dapm_new_controls(dapm, sdp3430_twl4030_dapm_widgets, - ARRAY_SIZE(sdp3430_twl4030_dapm_widgets)); - if (ret) - return ret; - - /* Set up SDP3430 specific audio path audio_map */ - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - /* SDP3430 connected pins */ snd_soc_dapm_enable_pin(dapm, "Ext Mic"); snd_soc_dapm_enable_pin(dapm, "Ext Spk"); @@ -223,10 +150,6 @@ static int sdp3430_twl4030_init(struct snd_soc_pcm_runtime *rtd) snd_soc_dapm_nc_pin(dapm, "CARKITL"); snd_soc_dapm_nc_pin(dapm, "CARKITR"); - ret = snd_soc_dapm_sync(dapm); - if (ret) - return ret; - /* Headset jack detection */ ret = snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET, &hs_jack); @@ -267,6 +190,8 @@ static struct snd_soc_dai_link sdp3430_dai[] = { .codec_dai_name = "twl4030-hifi", .platform_name = "omap-pcm-audio", .codec_name = "twl4030-codec", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBM_CFM, .init = sdp3430_twl4030_init, .ops = &sdp3430_ops, }, @@ -277,8 +202,10 @@ static struct snd_soc_dai_link sdp3430_dai[] = { .codec_dai_name = "twl4030-voice", .platform_name = "omap-pcm-audio", .codec_name = "twl4030-codec", + .dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF | + SND_SOC_DAIFMT_CBM_CFM, .init = sdp3430_twl4030_voice_init, - .ops = &sdp3430_voice_ops, + .ops = &sdp3430_ops, }, }; @@ -287,6 +214,11 @@ static struct snd_soc_card snd_soc_sdp3430 = { .name = "SDP3430", .dai_link = sdp3430_dai, .num_links = ARRAY_SIZE(sdp3430_dai), + + .dapm_widgets = sdp3430_twl4030_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sdp3430_twl4030_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static struct platform_device *sdp3430_snd_device; diff --git a/sound/soc/omap/sdp4430.c b/sound/soc/omap/sdp4430.c index b80efb02bfc..cc3d792af5e 100644 --- a/sound/soc/omap/sdp4430.c +++ b/sound/soc/omap/sdp4430.c @@ -32,7 +32,7 @@ #include <plat/hardware.h> #include <plat/mux.h> -#include "mcpdm.h" +#include "omap-mcpdm.h" #include "omap-pcm.h" #include "../codecs/twl6040.h" @@ -88,7 +88,7 @@ static const struct snd_soc_dapm_widget sdp4430_twl6040_dapm_widgets[] = { SND_SOC_DAPM_MIC("Headset Mic", NULL), SND_SOC_DAPM_HP("Headset Stereophone", NULL), SND_SOC_DAPM_SPK("Earphone Spk", NULL), - SND_SOC_DAPM_INPUT("Aux/FM Stereo In"), + SND_SOC_DAPM_INPUT("FM Stereo In"), }; static const struct snd_soc_dapm_route audio_map[] = { @@ -113,36 +113,22 @@ static const struct snd_soc_dapm_route audio_map[] = { {"Earphone Spk", NULL, "EP"}, /* Aux/FM Stereo In: AFML, AFMR */ - {"AFML", NULL, "Aux/FM Stereo In"}, - {"AFMR", NULL, "Aux/FM Stereo In"}, + {"AFML", NULL, "FM Stereo In"}, + {"AFMR", NULL, "FM Stereo In"}, }; static int sdp4430_twl6040_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - int ret; - - /* Add SDP4430 specific widgets */ - ret = snd_soc_dapm_new_controls(dapm, sdp4430_twl6040_dapm_widgets, - ARRAY_SIZE(sdp4430_twl6040_dapm_widgets)); - if (ret) - return ret; - - /* Set up SDP4430 specific audio path audio_map */ - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); + int ret, hs_trim; - /* SDP4430 connected pins */ - snd_soc_dapm_enable_pin(dapm, "Ext Mic"); - snd_soc_dapm_enable_pin(dapm, "Ext Spk"); - snd_soc_dapm_enable_pin(dapm, "AFML"); - snd_soc_dapm_enable_pin(dapm, "AFMR"); - snd_soc_dapm_enable_pin(dapm, "Headset Mic"); - snd_soc_dapm_enable_pin(dapm, "Headset Stereophone"); - - ret = snd_soc_dapm_sync(dapm); - if (ret) - return ret; + /* + * Configure McPDM offset cancellation based on the HSOTRIM value from + * twl6040. + */ + hs_trim = twl6040_get_trim_value(codec, TWL6040_TRIM_HSOTRIM); + omap_mcpdm_configure_dn_offsets(rtd, TWL6040_HSF_TRIM_LEFT(hs_trim), + TWL6040_HSF_TRIM_RIGHT(hs_trim)); /* Headset jack detection */ ret = snd_soc_jack_new(codec, "Headset Jack", @@ -165,8 +151,8 @@ static int sdp4430_twl6040_init(struct snd_soc_pcm_runtime *rtd) static struct snd_soc_dai_link sdp4430_dai = { .name = "TWL6040", .stream_name = "TWL6040", - .cpu_dai_name ="omap-mcpdm-dai", - .codec_dai_name = "twl6040-hifi", + .cpu_dai_name = "omap-mcpdm", + .codec_dai_name = "twl6040-legacy", .platform_name = "omap-pcm-audio", .codec_name = "twl6040-codec", .init = sdp4430_twl6040_init, @@ -178,6 +164,11 @@ static struct snd_soc_card snd_soc_sdp4430 = { .name = "SDP4430", .dai_link = &sdp4430_dai, .num_links = 1, + + .dapm_widgets = sdp4430_twl6040_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sdp4430_twl6040_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static struct platform_device *sdp4430_snd_device; diff --git a/sound/soc/omap/zoom2.c b/sound/soc/omap/zoom2.c index 9a2666ffc16..7cf35c82368 100644 --- a/sound/soc/omap/zoom2.c +++ b/sound/soc/omap/zoom2.c @@ -44,29 +44,8 @@ static int zoom2_hw_params(struct snd_pcm_substream *substream, { 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; - /* 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); @@ -82,49 +61,6 @@ static struct snd_soc_ops zoom2_ops = { .hw_params = zoom2_hw_params, }; -static int zoom2_hw_voice_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; - - /* Set codec DAI configuration */ - ret = snd_soc_dai_set_fmt(codec_dai, - SND_SOC_DAIFMT_DSP_A | - SND_SOC_DAIFMT_IB_NF | - SND_SOC_DAIFMT_CBM_CFM); - if (ret) { - 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_DSP_A | - SND_SOC_DAIFMT_IB_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 zoom2_voice_ops = { - .hw_params = zoom2_hw_voice_params, -}; - /* Zoom2 machine DAPM */ static const struct snd_soc_dapm_widget zoom2_twl4030_dapm_widgets[] = { SND_SOC_DAPM_MIC("Ext Mic", NULL), @@ -162,23 +98,6 @@ static int zoom2_twl4030_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; struct snd_soc_dapm_context *dapm = &codec->dapm; - int ret; - - /* Add Zoom2 specific widgets */ - ret = snd_soc_dapm_new_controls(dapm, zoom2_twl4030_dapm_widgets, - ARRAY_SIZE(zoom2_twl4030_dapm_widgets)); - if (ret) - return ret; - - /* Set up Zoom2 specific audio path audio_map */ - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - - /* Zoom2 connected pins */ - snd_soc_dapm_enable_pin(dapm, "Ext Mic"); - snd_soc_dapm_enable_pin(dapm, "Ext Spk"); - snd_soc_dapm_enable_pin(dapm, "Headset Mic"); - snd_soc_dapm_enable_pin(dapm, "Headset Stereophone"); - snd_soc_dapm_enable_pin(dapm, "Aux In"); /* TWL4030 not connected pins */ snd_soc_dapm_nc_pin(dapm, "CARKITMIC"); @@ -190,9 +109,7 @@ static int zoom2_twl4030_init(struct snd_soc_pcm_runtime *rtd) snd_soc_dapm_nc_pin(dapm, "CARKITL"); snd_soc_dapm_nc_pin(dapm, "CARKITR"); - ret = snd_soc_dapm_sync(dapm); - - return ret; + return 0; } static int zoom2_twl4030_voice_init(struct snd_soc_pcm_runtime *rtd) @@ -217,6 +134,8 @@ static struct snd_soc_dai_link zoom2_dai[] = { .codec_dai_name = "twl4030-hifi", .platform_name = "omap-pcm-audio", .codec_name = "twl4030-codec", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBM_CFM, .init = zoom2_twl4030_init, .ops = &zoom2_ops, }, @@ -227,8 +146,10 @@ static struct snd_soc_dai_link zoom2_dai[] = { .codec_dai_name = "twl4030-voice", .platform_name = "omap-pcm-audio", .codec_name = "twl4030-codec", + .dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF | + SND_SOC_DAIFMT_CBM_CFM, .init = zoom2_twl4030_voice_init, - .ops = &zoom2_voice_ops, + .ops = &zoom2_ops, }, }; @@ -237,6 +158,11 @@ static struct snd_soc_card snd_soc_zoom2 = { .name = "Zoom2", .dai_link = zoom2_dai, .num_links = ARRAY_SIZE(zoom2_dai), + + .dapm_widgets = zoom2_twl4030_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(zoom2_twl4030_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static struct platform_device *zoom2_snd_device; |