On Fri, Dec 17, 2010 at 02:41:28PM -0700, Stephen Warren wrote: > This provides an ASoC DAI interface for Tegra's I2S controller. > > Signed-off-by: Stephen Warren <swarren@xxxxxxxxxx> Again, broadly OK but needs to be redone against current ASoC versions - the device registration API has changed in 2.6.37 and there's a bunch more updates pending for 2.6.38. > --- > arch/arm/mach-tegra/Kconfig | 2 + > sound/soc/tegra/Kconfig | 13 ++ > sound/soc/tegra/Makefile | 2 + > sound/soc/tegra/tegra_i2s.c | 468 +++++++++++++++++++++++++++++++++++++++++++ > sound/soc/tegra/tegra_i2s.h | 166 +++++++++++++++ > 5 files changed, 651 insertions(+), 0 deletions(-) > create mode 100644 sound/soc/tegra/tegra_i2s.c > create mode 100644 sound/soc/tegra/tegra_i2s.h > > diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig > index d89d9b3..dedac6c 100644 > --- a/arch/arm/mach-tegra/Kconfig > +++ b/arch/arm/mach-tegra/Kconfig > @@ -102,3 +102,5 @@ config TEGRA_I2S_AUDIO > default n > help > Say Y if you want to add support for i2s audio on tegra. > + > + This option conflicts with SND_TEGRA_SOC_I2S. > diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig > index f568b2a..d6b0444 100644 > --- a/sound/soc/tegra/Kconfig > +++ b/sound/soc/tegra/Kconfig > @@ -4,3 +4,16 @@ config SND_TEGRA_SOC > default m > help > Say Y or M here if you want support for SoC audio on Tegra. > + > +config SND_TEGRA_SOC_I2S > + tristate > + depends on SND_TEGRA_SOC > + depends on !TEGRA_I2S_AUDIO > + default m > + help > + Say Y or M if you want to add support for codecs attached to the > + Tegra I2S interface. You will also need to select the individual > + machine drivers to support below. > + > + This option conflicts with TEGRA_I2S_AUDIO. > + > diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile > index 3c90e79..d7712a2 100644 > --- a/sound/soc/tegra/Makefile > +++ b/sound/soc/tegra/Makefile > @@ -1,7 +1,9 @@ > # Tegra platform Support > snd-soc-tegra-das-objs := tegra_das.o > snd-soc-tegra-pcm-objs := tegra_pcm.o > +snd-soc-tegra-i2s-objs := tegra_i2s.o > > obj-$(CONFIG_SND_TEGRA_SOC) += snd-soc-tegra-das.o > obj-$(CONFIG_SND_TEGRA_SOC) += snd-soc-tegra-pcm.o > +obj-$(CONFIG_SND_TEGRA_SOC_I2S) += snd-soc-tegra-i2s.o > > diff --git a/sound/soc/tegra/tegra_i2s.c b/sound/soc/tegra/tegra_i2s.c > new file mode 100644 > index 0000000..dd6547f > --- /dev/null > +++ b/sound/soc/tegra/tegra_i2s.c > @@ -0,0 +1,468 @@ > +/* > + * tegra_i2s.c - Tegra I2S driver > + * > + * Author: Stephen Warren <swarren@xxxxxxxxxx> > + * Copyright (C) 2010 - NVIDIA, Inc. > + * > + * Based on code copyright/by: > + * > + * Copyright (c) 2009-2010, NVIDIA Corporation. > + * Scott Peterson <speterson@xxxxxxxxxx> > + * > + * Copyright (C) 2010 Google, Inc. > + * Iliyan Malchev <malchev@xxxxxxxxxx> > + * > + * 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/debugfs.h> > +#include <linux/device.h> > +#include <linux/platform_device.h> > +#include <linux/seq_file.h> > +#include <linux/slab.h> > +#include <linux/io.h> > +#include <mach/iomap.h> > +#include <sound/core.h> > +#include <sound/pcm.h> > +#include <sound/pcm_params.h> > +#include <sound/soc.h> > + > +#include "tegra_i2s.h" > + > +#define DRV_NAME "tegra-i2s" > + > +static inline void tegra_i2s_write(struct tegra_i2s *i2s, u32 reg, u32 val) > +{ > + __raw_writel(val, i2s->regs + reg); > +} > + > +static inline u32 tegra_i2s_read(struct tegra_i2s *i2s, u32 reg) > +{ > + return __raw_readl(i2s->regs + reg); > +} > + > +#ifdef CONFIG_DEBUG_FS > +static int tegra_i2s_show(struct seq_file *s, void *unused) > +{ > +#define REG(r) { r, #r } > + static const struct { > + int offset; > + const char *name; > + } regs[] = { > + REG(TEGRA_I2S_CTRL), > + REG(TEGRA_I2S_STATUS), > + REG(TEGRA_I2S_TIMING), > + REG(TEGRA_I2S_FIFO_SCR), > + REG(TEGRA_I2S_PCM_CTRL), > + REG(TEGRA_I2S_NW_CTRL), > + REG(TEGRA_I2S_TDM_CTRL), > + REG(TEGRA_I2S_TDM_TX_RX_CTRL), > + }; > +#undef REG > + > + struct tegra_i2s *i2s = s->private; > + int i; > + > + for (i = 0; i < ARRAY_SIZE(regs); i++) { > + u32 val = tegra_i2s_read(i2s, regs[i].offset); > + seq_printf(s, "%s = %08x\n", regs[i].name, val); > + } > + > + return 0; > +} > + > +static int tegra_i2s_debug_open(struct inode *inode, struct file *file) > +{ > + return single_open(file, tegra_i2s_show, inode->i_private); > +} > + > +static const struct file_operations tegra_i2s_debug_fops = { > + .open = tegra_i2s_debug_open, > + .read = seq_read, > + .llseek = seq_lseek, > + .release = single_release, > +}; > + > +static void tegra_i2s_debug_add(struct tegra_i2s *i2s) > +{ > + char name[] = DRV_NAME ".0"; > + > + snprintf(name, sizeof(name), DRV_NAME".%1d", i2s->pdev->id); > + i2s->debug = debugfs_create_file(name, S_IRUGO, NULL, i2s, > + &tegra_i2s_debug_fops); Again, putting it under the ASoC directory would be a little nicer. > +} > + > +static void tegra_i2s_debug_remove(struct tegra_i2s *i2s) > +{ > + if (i2s->debug) > + debugfs_remove(i2s->debug); > +} > +#else > +static inline void tegra_i2s_debug_add(struct tegra_i2s *i2s) > +{ > +} > + > +static inline void tegra_i2s_debug_remove(struct tegra_i2s *i2s) > +{ > +} > +#endif > + > +static int tegra_i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, > + unsigned int freq, int dir) > +{ > + struct tegra_i2s *i2s = dai->private_data; > + > + i2s->sysclk = freq; > + > + return 0; > +} > + > +static int tegra_i2s_set_fmt(struct snd_soc_dai *dai, > + unsigned int fmt) > +{ > + struct tegra_i2s *i2s = dai->private_data; > + > + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { > + case SND_SOC_DAIFMT_NB_NF: > + break; > + case SND_SOC_DAIFMT_IB_IF: > + case SND_SOC_DAIFMT_IB_NF: > + case SND_SOC_DAIFMT_NB_IF: > + /* > + * Tegra does not support bit/frame clock inversion. > + */ > + default: > + return -EINVAL; It's not actually a problem but just having the default: case would be clear enough, no need for the case statements and comment (all they're doing as I'm reviewing this is looking like a common error pattern in code). > + } > + > + i2s->reg_ctrl &= ~TEGRA_I2S_CTRL_MASTER_ENABLE; > + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { > + case SND_SOC_DAIFMT_CBS_CFS: > + i2s->reg_ctrl |= TEGRA_I2S_CTRL_MASTER_ENABLE; > + break; > + case SND_SOC_DAIFMT_CBM_CFM: > + break; > + case SND_SOC_DAIFMT_CBS_CFM: > + case SND_SOC_DAIFMT_CBM_CFS: > + /* > + * Tegra does not support different combinations of > + * master and slave for FSYNC and BCLK > + */ > + default: > + return -EINVAL; > + } > + > + i2s->reg_ctrl &= ~(TEGRA_I2S_CTRL_BIT_FORMAT_MASK | > + TEGRA_I2S_CTRL_LRCK_MASK); > + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { > + case SND_SOC_DAIFMT_DSP_A: > + i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_FORMAT_DSP; > + i2s->reg_ctrl |= TEGRA_I2S_CTRL_LRCK_L_LOW; > + break; > + case SND_SOC_DAIFMT_DSP_B: > + i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_FORMAT_DSP; > + i2s->reg_ctrl |= TEGRA_I2S_CTRL_LRCK_R_LOW; > + break; > + case SND_SOC_DAIFMT_I2S: > + i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_FORMAT_I2S; > + i2s->reg_ctrl |= TEGRA_I2S_CTRL_LRCK_L_LOW; > + break; > + case SND_SOC_DAIFMT_RIGHT_J: > + i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_FORMAT_RJM; > + i2s->reg_ctrl |= TEGRA_I2S_CTRL_LRCK_L_LOW; > + break; > + case SND_SOC_DAIFMT_LEFT_J: > + i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_FORMAT_LJM; > + i2s->reg_ctrl |= TEGRA_I2S_CTRL_LRCK_L_LOW; > + break; > + default: > + return -EINVAL; > + } > + > + return 0; > +} > + > +static int tegra_i2s_hw_params(struct snd_pcm_substream *substream, > + struct snd_pcm_hw_params *params, > + struct snd_soc_dai *dai) > +{ > + struct tegra_i2s *i2s = dai->private_data; > + u32 reg; > + int srate; > + int bitcnt; > + > + i2s->reg_ctrl &= ~TEGRA_I2S_CTRL_BIT_SIZE_MASK; > + switch (params_format(params)) { > + case SNDRV_PCM_FORMAT_S16_LE: > + i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_SIZE_16; > + break; > + case SNDRV_PCM_FORMAT_S24_LE: > + i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_SIZE_24; > + break; > + case SNDRV_PCM_FORMAT_S32_LE: > + i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_SIZE_32; > + break; > + default: > + return -EINVAL; > + } > + > + srate = params_rate(params); > + bitcnt = (i2s->sysclk / (2 * srate)) - 1; > + if (bitcnt < 0 || bitcnt > TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US) > + return -EINVAL; > + reg = bitcnt << TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT; > + > + if (i2s->sysclk % (2 * srate)) > + reg |= TEGRA_I2S_TIMING_NON_SYM_ENABLE; > + > + tegra_i2s_write(i2s, TEGRA_I2S_TIMING, reg); > + > + tegra_i2s_write(i2s, TEGRA_I2S_FIFO_SCR, > + TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_FOUR_SLOTS | > + TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_FOUR_SLOTS); > + return 0; > +} > + > +static void tegra_i2s_start_playback(struct tegra_i2s *i2s) > +{ > + i2s->reg_ctrl |= TEGRA_I2S_CTRL_FIFO1_ENABLE; > + tegra_i2s_write(i2s, TEGRA_I2S_CTRL, i2s->reg_ctrl); > +} > + > +static void tegra_i2s_stop_playback(struct tegra_i2s *i2s) > +{ > + i2s->reg_ctrl &= ~TEGRA_I2S_CTRL_FIFO1_ENABLE; > + tegra_i2s_write(i2s, TEGRA_I2S_CTRL, i2s->reg_ctrl); > +} > + > +static void tegra_i2s_start_capture(struct tegra_i2s *i2s) > +{ > + i2s->reg_ctrl |= TEGRA_I2S_CTRL_FIFO2_ENABLE; > + tegra_i2s_write(i2s, TEGRA_I2S_CTRL, i2s->reg_ctrl); > +} > + > +static void tegra_i2s_stop_capture(struct tegra_i2s *i2s) > +{ > + i2s->reg_ctrl &= ~TEGRA_I2S_CTRL_FIFO2_ENABLE; > + tegra_i2s_write(i2s, TEGRA_I2S_CTRL, i2s->reg_ctrl); > +} > + > +static int tegra_i2s_trigger(struct snd_pcm_substream *substream, int cmd, > + struct snd_soc_dai *dai) > +{ > + struct tegra_i2s *i2s = dai->private_data; > + > + switch (cmd) { > + case SNDRV_PCM_TRIGGER_START: > + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: > + case SNDRV_PCM_TRIGGER_RESUME: > + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) > + tegra_i2s_start_playback(i2s); > + else > + tegra_i2s_start_capture(i2s); > + break; > + case SNDRV_PCM_TRIGGER_STOP: > + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: > + case SNDRV_PCM_TRIGGER_SUSPEND: > + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) > + tegra_i2s_stop_playback(i2s); > + else > + tegra_i2s_stop_capture(i2s); > + break; > + default: > + return -EINVAL; > + } > + > + return 0; > +} > + > +static struct snd_soc_dai_ops tegra_i2s_dai_ops = { > + .set_sysclk = tegra_i2s_set_sysclk, > + .set_fmt = tegra_i2s_set_fmt, > + .hw_params = tegra_i2s_hw_params, > + .trigger = tegra_i2s_trigger, You've got spaces for indentation on set_sysclk() there > +}; > + > +struct snd_soc_dai tegra_i2s_dai[] = { > + { > + .name = DRV_NAME ".0", > + .id = 0, > + .playback = { > + .channels_min = 2, > + .channels_max = 2, > + .rates = SNDRV_PCM_RATE_8000_96000, > + .formats = SNDRV_PCM_FMTBIT_S16_LE, > + }, > + .capture = { > + .channels_min = 2, > + .channels_max = 2, > + .rates = SNDRV_PCM_RATE_8000_96000, > + .formats = SNDRV_PCM_FMTBIT_S16_LE, > + }, > + .ops = &tegra_i2s_dai_ops, > + .symmetric_rates = 1, > + }, > + { > + .name = DRV_NAME ".1", > + .id = 1, > + .playback = { > + .channels_min = 2, > + .channels_max = 2, > + .rates = SNDRV_PCM_RATE_8000_96000, > + .formats = SNDRV_PCM_FMTBIT_S16_LE, > + }, > + .capture = { > + .channels_min = 2, > + .channels_max = 2, > + .rates = SNDRV_PCM_RATE_8000_96000, > + .formats = SNDRV_PCM_FMTBIT_S16_LE, > + }, > + .ops = &tegra_i2s_dai_ops, > + .symmetric_rates = 1, > + }, > +}; > +EXPORT_SYMBOL_GPL(tegra_i2s_dai); Yup, definitely not working with mainline here. Please update against current ASoC APIs - Linus' tree is probably OK at the minute, but ideally always develop against -next. > + > +static int tegra_i2s_probe(struct platform_device *pdev) > +{ > + static struct tegra_i2s * i2s; > + struct resource *mem, *memregion, *dmareq; > + int ret = 0; > + > + i2s = kzalloc(sizeof(struct tegra_i2s), GFP_KERNEL); > + if (!i2s) { > + dev_err(&pdev->dev, "Can't allocate tegra_i2s\n"); > + ret = -ENOMEM; > + goto exit; > + } > + i2s->pdev = pdev; > + > + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); > + if (!mem) { > + dev_err(&pdev->dev, "No memory resource\n"); > + ret = -ENODEV; > + goto err_free; > + } > + > + dmareq = platform_get_resource(pdev, IORESOURCE_DMA, 0); > + if (!dmareq) { > + dev_err(&pdev->dev, "No DMA resource\n"); > + ret = -ENODEV; > + goto err_free; > + } > + > + memregion = request_mem_region(mem->start, resource_size(mem), > + DRV_NAME); > + if (!memregion) { > + dev_err(&pdev->dev, "Memory region already claimed\n"); > + ret = -EBUSY; > + goto err_free; > + } > + > + i2s->regs = ioremap(mem->start, resource_size(mem)); > + if (!i2s->regs) { > + dev_err(&pdev->dev, "ioremap failed\n"); > + ret = -ENOMEM; > + goto err_release; > + } > + > + i2s->dma_params[0].addr = mem->start + TEGRA_I2S_FIFO2; > + i2s->dma_params[0].wrap = 4; > + i2s->dma_params[0].width = 32; > + i2s->dma_params[0].req_sel = dmareq->start; > + > + i2s->dma_params[1].addr = mem->start + TEGRA_I2S_FIFO1; > + i2s->dma_params[1].wrap = 4; > + i2s->dma_params[1].width = 32; > + i2s->dma_params[1].req_sel = dmareq->start; > + > + tegra_i2s_dai[pdev->id].private_data = i2s; > + tegra_i2s_dai[pdev->id].capture.dma_data = &i2s->dma_params[0]; > + tegra_i2s_dai[pdev->id].playback.dma_data = &i2s->dma_params[1]; > + tegra_i2s_dai[pdev->id].dev = &pdev->dev; > + > + ret = snd_soc_register_dai(&tegra_i2s_dai[pdev->id]); > + if (ret != 0) { > + dev_err(&pdev->dev, "Could not register DAI: %d\n", ret); > + ret = -ENOMEM; > + goto err_unmap; > + } > + > + tegra_i2s_debug_add(i2s); > + > + platform_set_drvdata(pdev, i2s); > + > + i2s->reg_ctrl = TEGRA_I2S_CTRL_FIFO_FORMAT_PACKED; > + > + return 0; > + > +err_unmap: > + iounmap(i2s->regs); > +err_release: > + release_mem_region(mem->start, resource_size(mem)); > +err_free: > + kfree(i2s); > +exit: > + return ret; > +} > + > +static int tegra_i2s_remove(struct platform_device *pdev) > +{ > + struct tegra_i2s *i2s = platform_get_drvdata(pdev); > + struct resource *res; > + > + platform_set_drvdata(pdev, NULL); > + > + tegra_i2s_debug_remove(i2s); > + > + snd_soc_unregister_dai(&tegra_i2s_dai[pdev->id]); > + > + iounmap(i2s->regs); > + > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > + release_mem_region(res->start, resource_size(res)); > + > + kfree(i2s); > + > + return 0; > +} > + > +static struct platform_driver tegra_i2s_driver = { > + .probe = tegra_i2s_probe, > + .remove = tegra_i2s_remove, > + .driver = { > + .name = DRV_NAME, > + .owner = THIS_MODULE, > + }, > +}; > + > +static int __init tegra_i2s_modinit(void) > +{ > + return platform_driver_register(&tegra_i2s_driver); > +} > +module_init(tegra_i2s_modinit); > + > +static void __exit tegra_i2s_modexit(void) > +{ > + platform_driver_unregister(&tegra_i2s_driver); > +} > +module_exit(tegra_i2s_modexit); > + > +MODULE_AUTHOR("Stephen Warren <swarren@xxxxxxxxxx>"); > +MODULE_DESCRIPTION("Tegra I2S ASoC driver"); > +MODULE_LICENSE("GPL"); > diff --git a/sound/soc/tegra/tegra_i2s.h b/sound/soc/tegra/tegra_i2s.h > new file mode 100644 > index 0000000..2396221 > --- /dev/null > +++ b/sound/soc/tegra/tegra_i2s.h > @@ -0,0 +1,166 @@ > +/* > + * tegra_i2s.h - Definitions for Tegra I2S driver > + * > + * Author: Stephen Warren <swarren@xxxxxxxxxx> > + * Copyright (C) 2010 - NVIDIA, Inc. > + * > + * Based on code copyright/by: > + * > + * Copyright (c) 2009-2010, NVIDIA Corporation. > + * Scott Peterson <speterson@xxxxxxxxxx> > + * > + * Copyright (C) 2010 Google, Inc. > + * Iliyan Malchev <malchev@xxxxxxxxxx> > + * > + * 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 __TEGRA_I2S_H__ > +#define __TEGRA_I2S_H__ > + > +#include "tegra_pcm.h" > + > +/* Register offsets from TEGRA_I2S1_BASE and TEGRA_I2S2_BASE */ > + > +#define TEGRA_I2S_CTRL 0x00 > +#define TEGRA_I2S_STATUS 0x04 > +#define TEGRA_I2S_TIMING 0x08 > +#define TEGRA_I2S_FIFO_SCR 0x0c > +#define TEGRA_I2S_PCM_CTRL 0x10 > +#define TEGRA_I2S_NW_CTRL 0x14 > +#define TEGRA_I2S_TDM_CTRL 0x20 > +#define TEGRA_I2S_TDM_TX_RX_CTRL 0x24 > +#define TEGRA_I2S_FIFO1 0x40 > +#define TEGRA_I2S_FIFO2 0x80 > + > +/* Fields in TEGRA_I2S_CTRL */ > + > +#define TEGRA_I2S_CTRL_FIFO2_TX_ENABLE (1 << 30) > +#define TEGRA_I2S_CTRL_FIFO1_ENABLE (1 << 29) > +#define TEGRA_I2S_CTRL_FIFO2_ENABLE (1 << 28) > +#define TEGRA_I2S_CTRL_FIFO1_RX_ENABLE (1 << 27) > +#define TEGRA_I2S_CTRL_FIFO_LPBK_ENABLE (1 << 26) > +#define TEGRA_I2S_CTRL_MASTER_ENABLE (1 << 25) > + > +#define I2S_LRCK_LEFT_LOW 0 > +#define I2S_LRCK_RIGHT_LOW 1 > +#define I2S_LRCK_SHIFT 24 > + > +#define TEGRA_I2S_CTRL_LRCK_MASK (1 << I2S_LRCK_SHIFT) > +#define TEGRA_I2S_CTRL_LRCK_L_LOW (I2S_LRCK_LEFT_LOW << I2S_LRCK_SHIFT) > +#define TEGRA_I2S_CTRL_LRCK_R_LOW (I2S_LRCK_RIGHT_LOW << I2S_LRCK_SHIFT) > + > +#define I2S_BIT_FORMAT_I2S 0 > +#define I2S_BIT_FORMAT_RJM 1 > +#define I2S_BIT_FORMAT_LJM 2 > +#define I2S_BIT_FORMAT_DSP 3 > +#define I2S_BIT_FORMAT_SHIFT 10 > + These need namespacing or moving into the driver, as do all the other I2S_ constants. > +#define TEGRA_I2S_CTRL_BIT_FORMAT_MASK (3 << I2S_BIT_FORMAT_SHIFT) > +#define TEGRA_I2S_CTRL_BIT_FORMAT_I2S (I2S_BIT_FORMAT_I2S << 10) > +#define TEGRA_I2S_CTRL_BIT_FORMAT_RJM (I2S_BIT_FORMAT_RJM << 10) > +#define TEGRA_I2S_CTRL_BIT_FORMAT_LJM (I2S_BIT_FORMAT_LJM << 10) > +#define TEGRA_I2S_CTRL_BIT_FORMAT_DSP (I2S_BIT_FORMAT_DSP << 10) > + > +#define I2S_BIT_SIZE_16 0 > +#define I2S_BIT_SIZE_20 1 > +#define I2S_BIT_SIZE_24 2 > +#define I2S_BIT_SIZE_32 3 > +#define I2S_BIT_SIZE_SHIFT 8 > + > +#define TEGRA_I2S_CTRL_BIT_SIZE_MASK (3 << I2S_BIT_SIZE_SHIFT) > +#define TEGRA_I2S_CTRL_BIT_SIZE_16 (I2S_BIT_SIZE_16 << I2S_BIT_SIZE_SHIFT) > +#define TEGRA_I2S_CTRL_BIT_SIZE_20 (I2S_BIT_SIZE_20 << I2S_BIT_SIZE_SHIFT) > +#define TEGRA_I2S_CTRL_BIT_SIZE_24 (I2S_BIT_SIZE_24 << I2S_BIT_SIZE_SHIFT) > +#define TEGRA_I2S_CTRL_BIT_SIZE_32 (I2S_BIT_SIZE_32 << I2S_BIT_SIZE_SHIFT) > + > +#define I2S_FIFO_16_LSB 0 > +#define I2S_FIFO_20_LSB 1 > +#define I2S_FIFO_24_LSB 2 > +#define I2S_FIFO_32 3 > +#define I2S_FIFO_PACKED 7 > +#define I2S_FIFO_SHIFT 4 > + > +#define TEGRA_I2S_CTRL_FIFO_FORMAT_MASK (7 << I2S_FIFO_SHIFT) > +#define TEGRA_I2S_CTRL_FIFO_FORMAT_16_LSB (I2S_FIFO_16_LSB << I2S_FIFO_SHIFT) > +#define TEGRA_I2S_CTRL_FIFO_FORMAT_20_LSB (I2S_FIFO_20_LSB << I2S_FIFO_SHIFT) > +#define TEGRA_I2S_CTRL_FIFO_FORMAT_24_LSB (I2S_FIFO_24_LSB << I2S_FIFO_SHIFT) > +#define TEGRA_I2S_CTRL_FIFO_FORMAT_32 (I2S_FIFO_32 << I2S_FIFO_SHIFT) > +#define TEGRA_I2S_CTRL_FIFO_FORMAT_PACKED (I2S_FIFO_PACKED << I2S_FIFO_SHIFT) > + > +#define TEGRA_I2S_CTRL_IE_FIFO1_ERR (1 << 3) > +#define TEGRA_I2S_CTRL_IE_FIFO2_ERR (1 << 2) > +#define TEGRA_I2S_CTRL_QE_FIFO1 (1 << 1) > +#define TEGRA_I2S_CTRL_QE_FIFO2 (1 << 0) > + > +/* Fields in TEGRA_I2S_STATUS */ > + > +#define TEGRA_I2S_STATUS_FIFO1_RDY (1 << 31) > +#define TEGRA_I2S_STATUS_FIFO2_RDY (1 << 30) > +#define TEGRA_I2S_STATUS_FIFO1_BSY (1 << 29) > +#define TEGRA_I2S_STATUS_FIFO2_BSY (1 << 28) > +#define TEGRA_I2S_STATUS_FIFO1_ERR (1 << 3) > +#define TEGRA_I2S_STATUS_FIFO2_ERR (1 << 2) > +#define TEGRA_I2S_STATUS_QS_FIFO1 (1 << 1) > +#define TEGRA_I2S_STATUS_QS_FIFO2 (1 << 0) > + > +/* Fields in TEGRA_I2S_TIMING */ > + > +#define TEGRA_I2S_TIMING_NON_SYM_ENABLE (1 << 12) > +#define TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT 0 > +#define TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US 0x7fff > +#define TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_MASK (TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US << TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT) > + > +/* Fields in TEGRA_I2S_FIFO_SCR */ > + > +#define TEGRA_I2S_FIFO_SCR_FIFO2_FULL_EMPTY_COUNT_SHIFT 24 > +#define TEGRA_I2S_FIFO_SCR_FIFO1_FULL_EMPTY_COUNT_SHIFT 16 > +#define TEGRA_I2S_FIFO_SCR_FIFO_FULL_EMPTY_COUNT_MASK 0x3f > + > +#define TEGRA_I2S_FIFO_SCR_FIFO2_CLR (1 << 12) > +#define TEGRA_I2S_FIFO_SCR_FIFO1_CLR (1 << 8) > + > +#define I2S_FIFO_ATN_LVL_ONE_SLOT 0 > +#define I2S_FIFO_ATN_LVL_FOUR_SLOTS 1 > +#define I2S_FIFO_ATN_LVL_EIGHT_SLOTS 2 > +#define I2S_FIFO_ATN_LVL_TWELVE_SLOTS 3 > +#define I2S_FIFO2_ATN_LVL_SHIFT 4 > +#define I2S_FIFO1_ATN_LVL_SHIFT 0 > + > +#define TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_MASK (3 << I2S_FIFO2_ATN_LVL_SHIFT) > +#define TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_ONE_SLOT (I2S_FIFO_ATN_LVL_ONE_SLOT << I2S_FIFO2_ATN_LVL_SHIFT) > +#define TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_FOUR_SLOTS (I2S_FIFO_ATN_LVL_FOUR_SLOTS << I2S_FIFO2_ATN_LVL_SHIFT) > +#define TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_EIGHT_SLOTS (I2S_FIFO_ATN_LVL_EIGHT_SLOTS << I2S_FIFO2_ATN_LVL_SHIFT) > +#define TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_TWELVE_SLOTS (I2S_FIFO_ATN_LVL_TWELVE_SLOTS << I2S_FIFO2_ATN_LVL_SHIFT) > + > +#define TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_MASK (3 << I2S_FIFO1_ATN_LVL_SHIFT) > +#define TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_ONE_SLOT (I2S_FIFO_ATN_LVL_ONE_SLOT << I2S_FIFO1_ATN_LVL_SHIFT) > +#define TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_FOUR_SLOTS (I2S_FIFO_ATN_LVL_FOUR_SLOTS << I2S_FIFO1_ATN_LVL_SHIFT) > +#define TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_EIGHT_SLOTS (I2S_FIFO_ATN_LVL_EIGHT_SLOTS << I2S_FIFO1_ATN_LVL_SHIFT) > +#define TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_TWELVE_SLOTS (I2S_FIFO_ATN_LVL_TWELVE_SLOTS << I2S_FIFO1_ATN_LVL_SHIFT) > + > +struct tegra_i2s { > + struct platform_device *pdev; > + struct tegra_pcm_dma_params dma_params[2]; > + void __iomem *regs; > + struct dentry *debug; > + unsigned int sysclk; > + u32 reg_ctrl; > +}; > + > +extern struct snd_soc_dai tegra_i2s_dai[]; > + > +#endif > -- > 1.7.0.4 > nvpublic > -- > To unsubscribe from this list: send the line "unsubscribe linux-tegra" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-tegra" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html