diff options
Diffstat (limited to 'ANDROID_3.4.5/sound/soc/davinci/davinci-mcasp.c')
-rw-r--r-- | ANDROID_3.4.5/sound/soc/davinci/davinci-mcasp.c | 983 |
1 files changed, 0 insertions, 983 deletions
diff --git a/ANDROID_3.4.5/sound/soc/davinci/davinci-mcasp.c b/ANDROID_3.4.5/sound/soc/davinci/davinci-mcasp.c deleted file mode 100644 index 95441bfc..00000000 --- a/ANDROID_3.4.5/sound/soc/davinci/davinci-mcasp.c +++ /dev/null @@ -1,983 +0,0 @@ -/* - * ALSA SoC McASP Audio Layer for TI DAVINCI processor - * - * Multi-channel Audio Serial Port Driver - * - * Author: Nirmal Pandey <n-pandey@ti.com>, - * Suresh Rajashekara <suresh.r@ti.com> - * Steve Chen <schen@.mvista.com> - * - * Copyright: (C) 2009 MontaVista Software, Inc., <source@mvista.com> - * Copyright: (C) 2009 Texas Instruments, India - * - * 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. - */ - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/device.h> -#include <linux/slab.h> -#include <linux/delay.h> -#include <linux/io.h> -#include <linux/clk.h> - -#include <sound/core.h> -#include <sound/pcm.h> -#include <sound/pcm_params.h> -#include <sound/initval.h> -#include <sound/soc.h> - -#include "davinci-pcm.h" -#include "davinci-mcasp.h" - -/* - * McASP register definitions - */ -#define DAVINCI_MCASP_PID_REG 0x00 -#define DAVINCI_MCASP_PWREMUMGT_REG 0x04 - -#define DAVINCI_MCASP_PFUNC_REG 0x10 -#define DAVINCI_MCASP_PDIR_REG 0x14 -#define DAVINCI_MCASP_PDOUT_REG 0x18 -#define DAVINCI_MCASP_PDSET_REG 0x1c - -#define DAVINCI_MCASP_PDCLR_REG 0x20 - -#define DAVINCI_MCASP_TLGC_REG 0x30 -#define DAVINCI_MCASP_TLMR_REG 0x34 - -#define DAVINCI_MCASP_GBLCTL_REG 0x44 -#define DAVINCI_MCASP_AMUTE_REG 0x48 -#define DAVINCI_MCASP_LBCTL_REG 0x4c - -#define DAVINCI_MCASP_TXDITCTL_REG 0x50 - -#define DAVINCI_MCASP_GBLCTLR_REG 0x60 -#define DAVINCI_MCASP_RXMASK_REG 0x64 -#define DAVINCI_MCASP_RXFMT_REG 0x68 -#define DAVINCI_MCASP_RXFMCTL_REG 0x6c - -#define DAVINCI_MCASP_ACLKRCTL_REG 0x70 -#define DAVINCI_MCASP_AHCLKRCTL_REG 0x74 -#define DAVINCI_MCASP_RXTDM_REG 0x78 -#define DAVINCI_MCASP_EVTCTLR_REG 0x7c - -#define DAVINCI_MCASP_RXSTAT_REG 0x80 -#define DAVINCI_MCASP_RXTDMSLOT_REG 0x84 -#define DAVINCI_MCASP_RXCLKCHK_REG 0x88 -#define DAVINCI_MCASP_REVTCTL_REG 0x8c - -#define DAVINCI_MCASP_GBLCTLX_REG 0xa0 -#define DAVINCI_MCASP_TXMASK_REG 0xa4 -#define DAVINCI_MCASP_TXFMT_REG 0xa8 -#define DAVINCI_MCASP_TXFMCTL_REG 0xac - -#define DAVINCI_MCASP_ACLKXCTL_REG 0xb0 -#define DAVINCI_MCASP_AHCLKXCTL_REG 0xb4 -#define DAVINCI_MCASP_TXTDM_REG 0xb8 -#define DAVINCI_MCASP_EVTCTLX_REG 0xbc - -#define DAVINCI_MCASP_TXSTAT_REG 0xc0 -#define DAVINCI_MCASP_TXTDMSLOT_REG 0xc4 -#define DAVINCI_MCASP_TXCLKCHK_REG 0xc8 -#define DAVINCI_MCASP_XEVTCTL_REG 0xcc - -/* Left(even TDM Slot) Channel Status Register File */ -#define DAVINCI_MCASP_DITCSRA_REG 0x100 -/* Right(odd TDM slot) Channel Status Register File */ -#define DAVINCI_MCASP_DITCSRB_REG 0x118 -/* Left(even TDM slot) User Data Register File */ -#define DAVINCI_MCASP_DITUDRA_REG 0x130 -/* Right(odd TDM Slot) User Data Register File */ -#define DAVINCI_MCASP_DITUDRB_REG 0x148 - -/* Serializer n Control Register */ -#define DAVINCI_MCASP_XRSRCTL_BASE_REG 0x180 -#define DAVINCI_MCASP_XRSRCTL_REG(n) (DAVINCI_MCASP_XRSRCTL_BASE_REG + \ - (n << 2)) - -/* Transmit Buffer for Serializer n */ -#define DAVINCI_MCASP_TXBUF_REG 0x200 -/* Receive Buffer for Serializer n */ -#define DAVINCI_MCASP_RXBUF_REG 0x280 - -/* McASP FIFO Registers */ -#define DAVINCI_MCASP_WFIFOCTL (0x1010) -#define DAVINCI_MCASP_WFIFOSTS (0x1014) -#define DAVINCI_MCASP_RFIFOCTL (0x1018) -#define DAVINCI_MCASP_RFIFOSTS (0x101C) - -/* - * DAVINCI_MCASP_PWREMUMGT_REG - Power Down and Emulation Management - * Register Bits - */ -#define MCASP_FREE BIT(0) -#define MCASP_SOFT BIT(1) - -/* - * DAVINCI_MCASP_PFUNC_REG - Pin Function / GPIO Enable Register Bits - */ -#define AXR(n) (1<<n) -#define PFUNC_AMUTE BIT(25) -#define ACLKX BIT(26) -#define AHCLKX BIT(27) -#define AFSX BIT(28) -#define ACLKR BIT(29) -#define AHCLKR BIT(30) -#define AFSR BIT(31) - -/* - * DAVINCI_MCASP_PDIR_REG - Pin Direction Register Bits - */ -#define AXR(n) (1<<n) -#define PDIR_AMUTE BIT(25) -#define ACLKX BIT(26) -#define AHCLKX BIT(27) -#define AFSX BIT(28) -#define ACLKR BIT(29) -#define AHCLKR BIT(30) -#define AFSR BIT(31) - -/* - * DAVINCI_MCASP_TXDITCTL_REG - Transmit DIT Control Register Bits - */ -#define DITEN BIT(0) /* Transmit DIT mode enable/disable */ -#define VA BIT(2) -#define VB BIT(3) - -/* - * DAVINCI_MCASP_TXFMT_REG - Transmit Bitstream Format Register Bits - */ -#define TXROT(val) (val) -#define TXSEL BIT(3) -#define TXSSZ(val) (val<<4) -#define TXPBIT(val) (val<<8) -#define TXPAD(val) (val<<13) -#define TXORD BIT(15) -#define FSXDLY(val) (val<<16) - -/* - * DAVINCI_MCASP_RXFMT_REG - Receive Bitstream Format Register Bits - */ -#define RXROT(val) (val) -#define RXSEL BIT(3) -#define RXSSZ(val) (val<<4) -#define RXPBIT(val) (val<<8) -#define RXPAD(val) (val<<13) -#define RXORD BIT(15) -#define FSRDLY(val) (val<<16) - -/* - * DAVINCI_MCASP_TXFMCTL_REG - Transmit Frame Control Register Bits - */ -#define FSXPOL BIT(0) -#define AFSXE BIT(1) -#define FSXDUR BIT(4) -#define FSXMOD(val) (val<<7) - -/* - * DAVINCI_MCASP_RXFMCTL_REG - Receive Frame Control Register Bits - */ -#define FSRPOL BIT(0) -#define AFSRE BIT(1) -#define FSRDUR BIT(4) -#define FSRMOD(val) (val<<7) - -/* - * DAVINCI_MCASP_ACLKXCTL_REG - Transmit Clock Control Register Bits - */ -#define ACLKXDIV(val) (val) -#define ACLKXE BIT(5) -#define TX_ASYNC BIT(6) -#define ACLKXPOL BIT(7) - -/* - * DAVINCI_MCASP_ACLKRCTL_REG Receive Clock Control Register Bits - */ -#define ACLKRDIV(val) (val) -#define ACLKRE BIT(5) -#define RX_ASYNC BIT(6) -#define ACLKRPOL BIT(7) - -/* - * DAVINCI_MCASP_AHCLKXCTL_REG - High Frequency Transmit Clock Control - * Register Bits - */ -#define AHCLKXDIV(val) (val) -#define AHCLKXPOL BIT(14) -#define AHCLKXE BIT(15) - -/* - * DAVINCI_MCASP_AHCLKRCTL_REG - High Frequency Receive Clock Control - * Register Bits - */ -#define AHCLKRDIV(val) (val) -#define AHCLKRPOL BIT(14) -#define AHCLKRE BIT(15) - -/* - * DAVINCI_MCASP_XRSRCTL_BASE_REG - Serializer Control Register Bits - */ -#define MODE(val) (val) -#define DISMOD (val)(val<<2) -#define TXSTATE BIT(4) -#define RXSTATE BIT(5) - -/* - * DAVINCI_MCASP_LBCTL_REG - Loop Back Control Register Bits - */ -#define LBEN BIT(0) -#define LBORD BIT(1) -#define LBGENMODE(val) (val<<2) - -/* - * DAVINCI_MCASP_TXTDMSLOT_REG - Transmit TDM Slot Register configuration - */ -#define TXTDMS(n) (1<<n) - -/* - * DAVINCI_MCASP_RXTDMSLOT_REG - Receive TDM Slot Register configuration - */ -#define RXTDMS(n) (1<<n) - -/* - * DAVINCI_MCASP_GBLCTL_REG - Global Control Register Bits - */ -#define RXCLKRST BIT(0) /* Receiver Clock Divider Reset */ -#define RXHCLKRST BIT(1) /* Receiver High Frequency Clock Divider */ -#define RXSERCLR BIT(2) /* Receiver Serializer Clear */ -#define RXSMRST BIT(3) /* Receiver State Machine Reset */ -#define RXFSRST BIT(4) /* Frame Sync Generator Reset */ -#define TXCLKRST BIT(8) /* Transmitter Clock Divider Reset */ -#define TXHCLKRST BIT(9) /* Transmitter High Frequency Clock Divider*/ -#define TXSERCLR BIT(10) /* Transmit Serializer Clear */ -#define TXSMRST BIT(11) /* Transmitter State Machine Reset */ -#define TXFSRST BIT(12) /* Frame Sync Generator Reset */ - -/* - * DAVINCI_MCASP_AMUTE_REG - Mute Control Register Bits - */ -#define MUTENA(val) (val) -#define MUTEINPOL BIT(2) -#define MUTEINENA BIT(3) -#define MUTEIN BIT(4) -#define MUTER BIT(5) -#define MUTEX BIT(6) -#define MUTEFSR BIT(7) -#define MUTEFSX BIT(8) -#define MUTEBADCLKR BIT(9) -#define MUTEBADCLKX BIT(10) -#define MUTERXDMAERR BIT(11) -#define MUTETXDMAERR BIT(12) - -/* - * DAVINCI_MCASP_REVTCTL_REG - Receiver DMA Event Control Register bits - */ -#define RXDATADMADIS BIT(0) - -/* - * DAVINCI_MCASP_XEVTCTL_REG - Transmitter DMA Event Control Register bits - */ -#define TXDATADMADIS BIT(0) - -/* - * DAVINCI_MCASP_W[R]FIFOCTL - Write/Read FIFO Control Register bits - */ -#define FIFO_ENABLE BIT(16) -#define NUMEVT_MASK (0xFF << 8) -#define NUMDMA_MASK (0xFF) - -#define DAVINCI_MCASP_NUM_SERIALIZER 16 - -static inline void mcasp_set_bits(void __iomem *reg, u32 val) -{ - __raw_writel(__raw_readl(reg) | val, reg); -} - -static inline void mcasp_clr_bits(void __iomem *reg, u32 val) -{ - __raw_writel((__raw_readl(reg) & ~(val)), reg); -} - -static inline void mcasp_mod_bits(void __iomem *reg, u32 val, u32 mask) -{ - __raw_writel((__raw_readl(reg) & ~mask) | val, reg); -} - -static inline void mcasp_set_reg(void __iomem *reg, u32 val) -{ - __raw_writel(val, reg); -} - -static inline u32 mcasp_get_reg(void __iomem *reg) -{ - return (unsigned int)__raw_readl(reg); -} - -static inline void mcasp_set_ctl_reg(void __iomem *regs, u32 val) -{ - int i = 0; - - mcasp_set_bits(regs, val); - - /* programming GBLCTL needs to read back from GBLCTL and verfiy */ - /* loop count is to avoid the lock-up */ - for (i = 0; i < 1000; i++) { - if ((mcasp_get_reg(regs) & val) == val) - break; - } - - if (i == 1000 && ((mcasp_get_reg(regs) & val) != val)) - printk(KERN_ERR "GBLCTL write error\n"); -} - -static void mcasp_start_rx(struct davinci_audio_dev *dev) -{ - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXHCLKRST); - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXCLKRST); - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSERCLR); - mcasp_set_reg(dev->base + DAVINCI_MCASP_RXBUF_REG, 0); - - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSMRST); - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXFSRST); - mcasp_set_reg(dev->base + DAVINCI_MCASP_RXBUF_REG, 0); - - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSMRST); - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXFSRST); -} - -static void mcasp_start_tx(struct davinci_audio_dev *dev) -{ - u8 offset = 0, i; - u32 cnt; - - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST); - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST); - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXSERCLR); - mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0); - - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXSMRST); - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXFSRST); - mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0); - for (i = 0; i < dev->num_serializer; i++) { - if (dev->serial_dir[i] == TX_MODE) { - offset = i; - break; - } - } - - /* wait for TX ready */ - cnt = 0; - while (!(mcasp_get_reg(dev->base + DAVINCI_MCASP_XRSRCTL_REG(offset)) & - TXSTATE) && (cnt < 100000)) - cnt++; - - mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0); -} - -static void davinci_mcasp_start(struct davinci_audio_dev *dev, int stream) -{ - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (dev->txnumevt) /* enable FIFO */ - mcasp_set_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, - FIFO_ENABLE); - mcasp_start_tx(dev); - } else { - if (dev->rxnumevt) /* enable FIFO */ - mcasp_set_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, - FIFO_ENABLE); - mcasp_start_rx(dev); - } -} - -static void mcasp_stop_rx(struct davinci_audio_dev *dev) -{ - mcasp_set_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, 0); - mcasp_set_reg(dev->base + DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF); -} - -static void mcasp_stop_tx(struct davinci_audio_dev *dev) -{ - mcasp_set_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, 0); - mcasp_set_reg(dev->base + DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF); -} - -static void davinci_mcasp_stop(struct davinci_audio_dev *dev, int stream) -{ - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (dev->txnumevt) /* disable FIFO */ - mcasp_clr_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, - FIFO_ENABLE); - mcasp_stop_tx(dev); - } else { - if (dev->rxnumevt) /* disable FIFO */ - mcasp_clr_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, - FIFO_ENABLE); - mcasp_stop_rx(dev); - } -} - -static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, - unsigned int fmt) -{ - struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); - void __iomem *base = dev->base; - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - /* codec is clock and frame slave */ - mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE); - mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE); - - mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE); - mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE); - - mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, - ACLKX | AHCLKX | AFSX); - break; - case SND_SOC_DAIFMT_CBM_CFS: - /* codec is clock master and frame slave */ - mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE); - mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE); - - mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE); - mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE); - - mcasp_clr_bits(base + DAVINCI_MCASP_PDIR_REG, - ACLKX | ACLKR); - mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, - AFSX | AFSR); - break; - case SND_SOC_DAIFMT_CBM_CFM: - /* codec is clock and frame master */ - mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE); - mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE); - - mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE); - mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE); - - mcasp_clr_bits(base + DAVINCI_MCASP_PDIR_REG, - ACLKX | AHCLKX | AFSX | ACLKR | AHCLKR | AFSR); - break; - - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_IB_NF: - mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); - mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); - - mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); - mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); - break; - - case SND_SOC_DAIFMT_NB_IF: - mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); - mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); - - mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); - mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); - break; - - case SND_SOC_DAIFMT_IB_IF: - mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); - mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); - - mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); - mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); - break; - - case SND_SOC_DAIFMT_NB_NF: - mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); - mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); - - mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); - mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); - break; - - default: - return -EINVAL; - } - - return 0; -} - -static int davinci_config_channel_size(struct davinci_audio_dev *dev, - int channel_size) -{ - u32 fmt = 0; - u32 mask, rotate; - - switch (channel_size) { - case DAVINCI_AUDIO_WORD_8: - fmt = 0x03; - rotate = 6; - mask = 0x000000ff; - break; - - case DAVINCI_AUDIO_WORD_12: - fmt = 0x05; - rotate = 5; - mask = 0x00000fff; - break; - - case DAVINCI_AUDIO_WORD_16: - fmt = 0x07; - rotate = 4; - mask = 0x0000ffff; - break; - - case DAVINCI_AUDIO_WORD_20: - fmt = 0x09; - rotate = 3; - mask = 0x000fffff; - break; - - case DAVINCI_AUDIO_WORD_24: - fmt = 0x0B; - rotate = 2; - mask = 0x00ffffff; - break; - - case DAVINCI_AUDIO_WORD_28: - fmt = 0x0D; - rotate = 1; - mask = 0x0fffffff; - break; - - case DAVINCI_AUDIO_WORD_32: - fmt = 0x0F; - rotate = 0; - mask = 0xffffffff; - break; - - default: - return -EINVAL; - } - - mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, - RXSSZ(fmt), RXSSZ(0x0F)); - mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, - TXSSZ(fmt), TXSSZ(0x0F)); - mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXROT(rotate), - TXROT(7)); - mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, RXROT(rotate), - RXROT(7)); - mcasp_set_reg(dev->base + DAVINCI_MCASP_TXMASK_REG, mask); - mcasp_set_reg(dev->base + DAVINCI_MCASP_RXMASK_REG, mask); - - return 0; -} - -static void davinci_hw_common_param(struct davinci_audio_dev *dev, int stream) -{ - int i; - u8 tx_ser = 0; - u8 rx_ser = 0; - - /* Default configuration */ - mcasp_set_bits(dev->base + DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT); - - /* All PINS as McASP */ - mcasp_set_reg(dev->base + DAVINCI_MCASP_PFUNC_REG, 0x00000000); - - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - mcasp_set_reg(dev->base + DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF); - mcasp_clr_bits(dev->base + DAVINCI_MCASP_XEVTCTL_REG, - TXDATADMADIS); - } else { - mcasp_set_reg(dev->base + DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF); - mcasp_clr_bits(dev->base + DAVINCI_MCASP_REVTCTL_REG, - RXDATADMADIS); - } - - for (i = 0; i < dev->num_serializer; i++) { - mcasp_set_bits(dev->base + DAVINCI_MCASP_XRSRCTL_REG(i), - dev->serial_dir[i]); - if (dev->serial_dir[i] == TX_MODE) { - mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG, - AXR(i)); - tx_ser++; - } else if (dev->serial_dir[i] == RX_MODE) { - mcasp_clr_bits(dev->base + DAVINCI_MCASP_PDIR_REG, - AXR(i)); - rx_ser++; - } - } - - if (dev->txnumevt && stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (dev->txnumevt * tx_ser > 64) - dev->txnumevt = 1; - - mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, tx_ser, - NUMDMA_MASK); - mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, - ((dev->txnumevt * tx_ser) << 8), NUMEVT_MASK); - } - - if (dev->rxnumevt && stream == SNDRV_PCM_STREAM_CAPTURE) { - if (dev->rxnumevt * rx_ser > 64) - dev->rxnumevt = 1; - - mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, rx_ser, - NUMDMA_MASK); - mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, - ((dev->rxnumevt * rx_ser) << 8), NUMEVT_MASK); - } -} - -static void davinci_hw_param(struct davinci_audio_dev *dev, int stream) -{ - int i, active_slots; - u32 mask = 0; - - active_slots = (dev->tdm_slots > 31) ? 32 : dev->tdm_slots; - for (i = 0; i < active_slots; i++) - mask |= (1 << i); - - mcasp_clr_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG, TX_ASYNC); - - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - /* bit stream is MSB first with no delay */ - /* DSP_B mode */ - mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, - AHCLKXE); - mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, mask); - mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXORD); - - if ((dev->tdm_slots >= 2) && (dev->tdm_slots <= 32)) - mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, - FSXMOD(dev->tdm_slots), FSXMOD(0x1FF)); - else - printk(KERN_ERR "playback tdm slot %d not supported\n", - dev->tdm_slots); - - mcasp_clr_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR); - } else { - /* bit stream is MSB first with no delay */ - /* DSP_B mode */ - mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, RXORD); - mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG, - AHCLKRE); - mcasp_set_reg(dev->base + DAVINCI_MCASP_RXTDM_REG, mask); - - if ((dev->tdm_slots >= 2) && (dev->tdm_slots <= 32)) - mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, - FSRMOD(dev->tdm_slots), FSRMOD(0x1FF)); - else - printk(KERN_ERR "capture tdm slot %d not supported\n", - dev->tdm_slots); - - mcasp_clr_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR); - } -} - -/* S/PDIF */ -static void davinci_hw_dit_param(struct davinci_audio_dev *dev) -{ - /* Set the PDIR for Serialiser as output */ - mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG, AFSX); - - /* TXMASK for 24 bits */ - mcasp_set_reg(dev->base + DAVINCI_MCASP_TXMASK_REG, 0x00FFFFFF); - - /* Set the TX format : 24 bit right rotation, 32 bit slot, Pad 0 - and LSB first */ - mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, - TXROT(6) | TXSSZ(15)); - - /* Set TX frame synch : DIT Mode, 1 bit width, internal, rising edge */ - mcasp_set_reg(dev->base + DAVINCI_MCASP_TXFMCTL_REG, - AFSXE | FSXMOD(0x180)); - - /* Set the TX tdm : for all the slots */ - mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, 0xFFFFFFFF); - - /* Set the TX clock controls : div = 1 and internal */ - mcasp_set_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG, - ACLKXE | TX_ASYNC); - - mcasp_clr_bits(dev->base + DAVINCI_MCASP_XEVTCTL_REG, TXDATADMADIS); - - /* Only 44100 and 48000 are valid, both have the same setting */ - mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXDIV(3)); - - /* Enable the DIT */ - mcasp_set_bits(dev->base + DAVINCI_MCASP_TXDITCTL_REG, DITEN); -} - -static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *cpu_dai) -{ - struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); - struct davinci_pcm_dma_params *dma_params = - &dev->dma_params[substream->stream]; - int word_length; - u8 fifo_level; - - davinci_hw_common_param(dev, substream->stream); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - fifo_level = dev->txnumevt; - else - fifo_level = dev->rxnumevt; - - if (dev->op_mode == DAVINCI_MCASP_DIT_MODE) - davinci_hw_dit_param(dev); - else - davinci_hw_param(dev, substream->stream); - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_U8: - case SNDRV_PCM_FORMAT_S8: - dma_params->data_type = 1; - word_length = DAVINCI_AUDIO_WORD_8; - break; - - case SNDRV_PCM_FORMAT_U16_LE: - case SNDRV_PCM_FORMAT_S16_LE: - dma_params->data_type = 2; - word_length = DAVINCI_AUDIO_WORD_16; - break; - - case SNDRV_PCM_FORMAT_U32_LE: - case SNDRV_PCM_FORMAT_S32_LE: - dma_params->data_type = 4; - word_length = DAVINCI_AUDIO_WORD_32; - break; - - default: - printk(KERN_WARNING "davinci-mcasp: unsupported PCM format"); - return -EINVAL; - } - - if (dev->version == MCASP_VERSION_2 && !fifo_level) - dma_params->acnt = 4; - else - dma_params->acnt = dma_params->data_type; - - dma_params->fifo_level = fifo_level; - davinci_config_channel_size(dev, word_length); - - return 0; -} - -static int davinci_mcasp_trigger(struct snd_pcm_substream *substream, - int cmd, struct snd_soc_dai *cpu_dai) -{ - struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); - int ret = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if (!dev->clk_active) { - clk_enable(dev->clk); - dev->clk_active = 1; - } - davinci_mcasp_start(dev, substream->stream); - break; - - case SNDRV_PCM_TRIGGER_SUSPEND: - davinci_mcasp_stop(dev, substream->stream); - if (dev->clk_active) { - clk_disable(dev->clk); - dev->clk_active = 0; - } - - break; - - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - davinci_mcasp_stop(dev, substream->stream); - break; - - default: - ret = -EINVAL; - } - - return ret; -} - -static int davinci_mcasp_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(dai); - - snd_soc_dai_set_dma_data(dai, substream, dev->dma_params); - return 0; -} - -static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = { - .startup = davinci_mcasp_startup, - .trigger = davinci_mcasp_trigger, - .hw_params = davinci_mcasp_hw_params, - .set_fmt = davinci_mcasp_set_dai_fmt, - -}; - -#define DAVINCI_MCASP_PCM_FMTS (SNDRV_PCM_FMTBIT_S8 | \ - SNDRV_PCM_FMTBIT_U8 | \ - SNDRV_PCM_FMTBIT_S16_LE | \ - SNDRV_PCM_FMTBIT_U16_LE | \ - SNDRV_PCM_FMTBIT_S32_LE | \ - SNDRV_PCM_FMTBIT_U32_LE) - -static struct snd_soc_dai_driver davinci_mcasp_dai[] = { - { - .name = "davinci-mcasp.0", - .playback = { - .channels_min = 2, - .channels_max = 2, - .rates = DAVINCI_MCASP_RATES, - .formats = DAVINCI_MCASP_PCM_FMTS, - }, - .capture = { - .channels_min = 2, - .channels_max = 2, - .rates = DAVINCI_MCASP_RATES, - .formats = DAVINCI_MCASP_PCM_FMTS, - }, - .ops = &davinci_mcasp_dai_ops, - - }, - { - "davinci-mcasp.1", - .playback = { - .channels_min = 1, - .channels_max = 384, - .rates = DAVINCI_MCASP_RATES, - .formats = DAVINCI_MCASP_PCM_FMTS, - }, - .ops = &davinci_mcasp_dai_ops, - }, - -}; - -static int davinci_mcasp_probe(struct platform_device *pdev) -{ - struct davinci_pcm_dma_params *dma_data; - struct resource *mem, *ioarea, *res; - struct snd_platform_data *pdata; - struct davinci_audio_dev *dev; - int ret; - - dev = devm_kzalloc(&pdev->dev, sizeof(struct davinci_audio_dev), - GFP_KERNEL); - if (!dev) - return -ENOMEM; - - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!mem) { - dev_err(&pdev->dev, "no mem resource?\n"); - return -ENODEV; - } - - ioarea = devm_request_mem_region(&pdev->dev, mem->start, - resource_size(mem), pdev->name); - if (!ioarea) { - dev_err(&pdev->dev, "Audio region already claimed\n"); - return -EBUSY; - } - - pdata = pdev->dev.platform_data; - dev->clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(dev->clk)) - return -ENODEV; - - clk_enable(dev->clk); - dev->clk_active = 1; - - dev->base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); - if (!dev->base) { - dev_err(&pdev->dev, "ioremap failed\n"); - ret = -ENOMEM; - goto err_release_clk; - } - - dev->op_mode = pdata->op_mode; - dev->tdm_slots = pdata->tdm_slots; - dev->num_serializer = pdata->num_serializer; - dev->serial_dir = pdata->serial_dir; - dev->codec_fmt = pdata->codec_fmt; - dev->version = pdata->version; - dev->txnumevt = pdata->txnumevt; - dev->rxnumevt = pdata->rxnumevt; - - dma_data = &dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]; - dma_data->asp_chan_q = pdata->asp_chan_q; - dma_data->ram_chan_q = pdata->ram_chan_q; - dma_data->sram_size = pdata->sram_size_playback; - dma_data->dma_addr = (dma_addr_t) (pdata->tx_dma_offset + - mem->start); - - /* first TX, then RX */ - res = platform_get_resource(pdev, IORESOURCE_DMA, 0); - if (!res) { - dev_err(&pdev->dev, "no DMA resource\n"); - ret = -ENODEV; - goto err_release_clk; - } - - dma_data->channel = res->start; - - dma_data = &dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]; - dma_data->asp_chan_q = pdata->asp_chan_q; - dma_data->ram_chan_q = pdata->ram_chan_q; - dma_data->sram_size = pdata->sram_size_capture; - dma_data->dma_addr = (dma_addr_t)(pdata->rx_dma_offset + - mem->start); - - res = platform_get_resource(pdev, IORESOURCE_DMA, 1); - if (!res) { - dev_err(&pdev->dev, "no DMA resource\n"); - ret = -ENODEV; - goto err_release_clk; - } - - dma_data->channel = res->start; - dev_set_drvdata(&pdev->dev, dev); - ret = snd_soc_register_dai(&pdev->dev, &davinci_mcasp_dai[pdata->op_mode]); - - if (ret != 0) - goto err_release_clk; - return 0; - -err_release_clk: - clk_disable(dev->clk); - clk_put(dev->clk); - return ret; -} - -static int davinci_mcasp_remove(struct platform_device *pdev) -{ - struct davinci_audio_dev *dev = dev_get_drvdata(&pdev->dev); - - snd_soc_unregister_dai(&pdev->dev); - clk_disable(dev->clk); - clk_put(dev->clk); - dev->clk = NULL; - - return 0; -} - -static struct platform_driver davinci_mcasp_driver = { - .probe = davinci_mcasp_probe, - .remove = davinci_mcasp_remove, - .driver = { - .name = "davinci-mcasp", - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(davinci_mcasp_driver); - -MODULE_AUTHOR("Steve Chen"); -MODULE_DESCRIPTION("TI DAVINCI McASP SoC Interface"); -MODULE_LICENSE("GPL"); - |