Merge branch 'for-3.1' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound-2.6 into topic/asoc

This commit is contained in:
Takashi Iwai 2011-07-09 11:43:04 +02:00
commit e320bc42be
12 changed files with 976 additions and 30 deletions

View file

@ -447,6 +447,7 @@ struct snd_soc_dapm_widget {
char *name; /* widget name */
char *sname; /* stream name */
struct snd_soc_codec *codec;
struct snd_soc_platform *platform;
struct list_head list;
struct snd_soc_dapm_context *dapm;
@ -510,6 +511,7 @@ struct snd_soc_dapm_context {
struct device *dev; /* from parent - for debug */
struct snd_soc_codec *codec; /* parent codec */
struct snd_soc_platform *platform; /* parent platform */
struct snd_soc_card *card; /* parent card */
/* used during DAPM updates */

View file

@ -368,6 +368,8 @@ struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
const char *prefix);
int snd_soc_add_controls(struct snd_soc_codec *codec,
const struct snd_kcontrol_new *controls, int num_controls);
int snd_soc_add_platform_controls(struct snd_soc_platform *platform,
const struct snd_kcontrol_new *controls, int num_controls);
int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo);
int snd_soc_info_enum_ext(struct snd_kcontrol *kcontrol,
@ -649,6 +651,14 @@ struct snd_soc_platform_driver {
int (*pcm_new)(struct snd_soc_pcm_runtime *);
void (*pcm_free)(struct snd_pcm *);
/* Default control and setup, added after probe() is run */
const struct snd_kcontrol_new *controls;
int num_controls;
const struct snd_soc_dapm_widget *dapm_widgets;
int num_dapm_widgets;
const struct snd_soc_dapm_route *dapm_routes;
int num_dapm_routes;
/*
* For platform caused delay reporting.
* Optional.
@ -680,6 +690,8 @@ struct snd_soc_platform {
struct snd_soc_card *card;
struct list_head list;
struct list_head card_list;
struct snd_soc_dapm_context dapm;
};
struct snd_soc_dai_link {

View file

@ -9,6 +9,7 @@
struct snd_soc_jack;
struct snd_soc_codec;
struct snd_soc_platform;
struct snd_soc_card;
struct snd_soc_dapm_widget;
@ -59,6 +60,50 @@ DEFINE_EVENT(snd_soc_reg, snd_soc_reg_read,
);
DECLARE_EVENT_CLASS(snd_soc_preg,
TP_PROTO(struct snd_soc_platform *platform, unsigned int reg,
unsigned int val),
TP_ARGS(platform, reg, val),
TP_STRUCT__entry(
__string( name, platform->name )
__field( int, id )
__field( unsigned int, reg )
__field( unsigned int, val )
),
TP_fast_assign(
__assign_str(name, platform->name);
__entry->id = platform->id;
__entry->reg = reg;
__entry->val = val;
),
TP_printk("platform=%s.%d reg=%x val=%x", __get_str(name),
(int)__entry->id, (unsigned int)__entry->reg,
(unsigned int)__entry->val)
);
DEFINE_EVENT(snd_soc_preg, snd_soc_preg_write,
TP_PROTO(struct snd_soc_platform *platform, unsigned int reg,
unsigned int val),
TP_ARGS(platform, reg, val)
);
DEFINE_EVENT(snd_soc_preg, snd_soc_preg_read,
TP_PROTO(struct snd_soc_platform *platform, unsigned int reg,
unsigned int val),
TP_ARGS(platform, reg, val)
);
DECLARE_EVENT_CLASS(snd_soc_card,
TP_PROTO(struct snd_soc_card *card, int val),

View file

@ -357,7 +357,7 @@ static int ak4642_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
default:
return -EINVAL;
}
snd_soc_update_bits(codec, PW_MGMT2, MS, data);
snd_soc_update_bits(codec, PW_MGMT2, MS | MCKO | PMPLL, data);
snd_soc_update_bits(codec, MD_CTL1, BCKO_MASK, bcko);
/* format type */

View file

@ -175,6 +175,7 @@ static const struct snd_kcontrol_new wm8731_input_mux_controls =
SOC_DAPM_ENUM("Input Select", wm8731_insel_enum);
static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY("ACTIVE",WM8731_ACTIVE, 0, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("OSC", WM8731_PWR, 5, 1, NULL, 0),
SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1,
&wm8731_output_mixer_controls[0],
@ -204,6 +205,8 @@ static int wm8731_check_osc(struct snd_soc_dapm_widget *source,
static const struct snd_soc_dapm_route wm8731_intercon[] = {
{"DAC", NULL, "OSC", wm8731_check_osc},
{"ADC", NULL, "OSC", wm8731_check_osc},
{"DAC", NULL, "ACTIVE"},
{"ADC", NULL, "ACTIVE"},
/* output mixer */
{"Output Mixer", "Line Bypass Switch", "Line Input"},
@ -315,29 +318,6 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream,
return 0;
}
static int wm8731_pcm_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_codec *codec = dai->codec;
/* set active */
snd_soc_write(codec, WM8731_ACTIVE, 0x0001);
return 0;
}
static void wm8731_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_codec *codec = dai->codec;
/* deactivate */
if (!codec->active) {
udelay(50);
snd_soc_write(codec, WM8731_ACTIVE, 0x0);
}
}
static int wm8731_mute(struct snd_soc_dai *dai, int mute)
{
struct snd_soc_codec *codec = dai->codec;
@ -480,7 +460,6 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec,
snd_soc_write(codec, WM8731_PWR, reg | 0x0040);
break;
case SND_SOC_BIAS_OFF:
snd_soc_write(codec, WM8731_ACTIVE, 0x0);
snd_soc_write(codec, WM8731_PWR, 0xffff);
regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies),
wm8731->supplies);
@ -496,9 +475,7 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec,
SNDRV_PCM_FMTBIT_S24_LE)
static struct snd_soc_dai_ops wm8731_dai_ops = {
.prepare = wm8731_pcm_prepare,
.hw_params = wm8731_hw_params,
.shutdown = wm8731_shutdown,
.digital_mute = wm8731_mute,
.set_sysclk = wm8731_set_dai_sysclk,
.set_fmt = wm8731_set_dai_fmt,

View file

@ -88,7 +88,6 @@ static u64 pxa2xx_pcm_dmamask = DMA_BIT_MASK(32);
static int pxa2xx_soc_pcm_new(struct snd_soc_pcm_runtime *rtd)
{
struct snd_card *card = rtd->card->snd_card;
struct snd_soc_dai *dai = rtd->cpu_dai;
struct snd_pcm *pcm = rtd->pcm;
int ret = 0;

View file

@ -993,10 +993,15 @@ static int soc_probe_platform(struct snd_soc_card *card,
const struct snd_soc_platform_driver *driver = platform->driver;
platform->card = card;
platform->dapm.card = card;
if (!try_module_get(platform->dev->driver->owner))
return -ENODEV;
if (driver->dapm_widgets)
snd_soc_dapm_new_controls(&platform->dapm,
driver->dapm_widgets, driver->num_dapm_widgets);
if (driver->probe) {
ret = driver->probe(platform);
if (ret < 0) {
@ -1007,9 +1012,17 @@ static int soc_probe_platform(struct snd_soc_card *card,
}
}
if (driver->controls)
snd_soc_add_platform_controls(platform, driver->controls,
driver->num_controls);
if (driver->dapm_routes)
snd_soc_dapm_add_routes(&platform->dapm, driver->dapm_routes,
driver->num_dapm_routes);
/* mark platform as probed and add to card platform list */
platform->probed = 1;
list_add(&platform->card_list, &card->platform_dev_list);
list_add(&platform->dapm.list, &card->dapm_list);
return 0;
@ -1652,6 +1665,7 @@ int snd_soc_platform_read(struct snd_soc_platform *platform,
ret = platform->driver->read(platform, reg);
dev_dbg(platform->dev, "read %x => %x\n", reg, ret);
trace_snd_soc_preg_read(platform, reg, ret);
return ret;
}
@ -1666,6 +1680,7 @@ int snd_soc_platform_write(struct snd_soc_platform *platform,
}
dev_dbg(platform->dev, "write %x = %x\n", reg, val);
trace_snd_soc_preg_write(platform, reg, val);
return platform->driver->write(platform, reg, val);
}
EXPORT_SYMBOL_GPL(snd_soc_platform_write);
@ -1948,6 +1963,36 @@ int snd_soc_add_controls(struct snd_soc_codec *codec,
}
EXPORT_SYMBOL_GPL(snd_soc_add_controls);
/**
* snd_soc_add_platform_controls - add an array of controls to a platform.
* Convienience function to add a list of controls.
*
* @platform: platform to add controls to
* @controls: array of controls to add
* @num_controls: number of elements in the array
*
* Return 0 for success, else error.
*/
int snd_soc_add_platform_controls(struct snd_soc_platform *platform,
const struct snd_kcontrol_new *controls, int num_controls)
{
struct snd_card *card = platform->card->snd_card;
int err, i;
for (i = 0; i < num_controls; i++) {
const struct snd_kcontrol_new *control = &controls[i];
err = snd_ctl_add(card, snd_soc_cnew(control, platform,
control->name, NULL));
if (err < 0) {
dev_err(platform->dev, "Failed to add %s %d\n",control->name, err);
return err;
}
}
return 0;
}
EXPORT_SYMBOL_GPL(snd_soc_add_platform_controls);
/**
* snd_soc_info_enum_double - enumerated double mixer info callback
* @kcontrol: mixer control
@ -3092,6 +3137,8 @@ int snd_soc_register_platform(struct device *dev,
platform->dev = dev;
platform->driver = platform_drv;
platform->dapm.dev = dev;
platform->dapm.platform = platform;
mutex_lock(&client_mutex);
list_add(&platform->list, &platform_list);

View file

@ -128,14 +128,22 @@ static int soc_widget_read(struct snd_soc_dapm_widget *w, int reg)
{
if (w->codec)
return snd_soc_read(w->codec, reg);
return 0;
else if (w->platform)
return snd_soc_platform_read(w->platform, reg);
dev_err(w->dapm->dev, "no valid widget read method\n");
return -1;
}
static int soc_widget_write(struct snd_soc_dapm_widget *w, int reg, int val)
{
if (w->codec)
return snd_soc_write(w->codec, reg, val);
return 0;
else if (w->platform)
return snd_soc_platform_write(w->platform, reg, val);
dev_err(w->dapm->dev, "no valid widget write method\n");
return -1;
}
static int soc_widget_update_bits(struct snd_soc_dapm_widget *w,
@ -2495,6 +2503,7 @@ int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
dapm->n_widgets++;
w->dapm = dapm;
w->codec = dapm->codec;
w->platform = dapm->platform;
INIT_LIST_HEAD(&w->sources);
INIT_LIST_HEAD(&w->sinks);
INIT_LIST_HEAD(&w->list);

View file

@ -12,6 +12,15 @@ config SND_SOC_TEGRA_I2S
Tegra I2S interface. You will also need to select the individual
machine drivers to support below.
config SND_SOC_TEGRA_SPDIF
tristate
depends on SND_SOC_TEGRA
default m
help
Say Y or M if you want to add support for the SPDIF interface.
You will also need to select the individual machine drivers to support
below.
config MACH_HAS_SND_SOC_TEGRA_WM8903
bool
help

View file

@ -2,12 +2,14 @@
snd-soc-tegra-das-objs := tegra_das.o
snd-soc-tegra-pcm-objs := tegra_pcm.o
snd-soc-tegra-i2s-objs := tegra_i2s.o
snd-soc-tegra-spdif-objs := tegra_spdif.o
snd-soc-tegra-utils-objs += tegra_asoc_utils.o
obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-utils.o
obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-das.o
obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-pcm.o
obj-$(CONFIG_SND_SOC_TEGRA_I2S) += snd-soc-tegra-i2s.o
obj-$(CONFIG_SND_SOC_TEGRA_SPDIF) += snd-soc-tegra-spdif.o
# Tegra machine Support
snd-soc-tegra-wm8903-objs := tegra_wm8903.o

View file

@ -0,0 +1,371 @@
/*
* tegra_spdif.c - Tegra SPDIF driver
*
* Author: Stephen Warren <swarren@nvidia.com>
* Copyright (C) 2011 - NVIDIA, 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/clk.h>
#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_spdif.h"
#define DRV_NAME "tegra-spdif"
static inline void tegra_spdif_write(struct tegra_spdif *spdif, u32 reg,
u32 val)
{
__raw_writel(val, spdif->regs + reg);
}
static inline u32 tegra_spdif_read(struct tegra_spdif *spdif, u32 reg)
{
return __raw_readl(spdif->regs + reg);
}
#ifdef CONFIG_DEBUG_FS
static int tegra_spdif_show(struct seq_file *s, void *unused)
{
#define REG(r) { r, #r }
static const struct {
int offset;
const char *name;
} regs[] = {
REG(TEGRA_SPDIF_CTRL),
REG(TEGRA_SPDIF_STATUS),
REG(TEGRA_SPDIF_STROBE_CTRL),
REG(TEGRA_SPDIF_DATA_FIFO_CSR),
REG(TEGRA_SPDIF_CH_STA_RX_A),
REG(TEGRA_SPDIF_CH_STA_RX_B),
REG(TEGRA_SPDIF_CH_STA_RX_C),
REG(TEGRA_SPDIF_CH_STA_RX_D),
REG(TEGRA_SPDIF_CH_STA_RX_E),
REG(TEGRA_SPDIF_CH_STA_RX_F),
REG(TEGRA_SPDIF_CH_STA_TX_A),
REG(TEGRA_SPDIF_CH_STA_TX_B),
REG(TEGRA_SPDIF_CH_STA_TX_C),
REG(TEGRA_SPDIF_CH_STA_TX_D),
REG(TEGRA_SPDIF_CH_STA_TX_E),
REG(TEGRA_SPDIF_CH_STA_TX_F),
};
#undef REG
struct tegra_spdif *spdif = s->private;
int i;
for (i = 0; i < ARRAY_SIZE(regs); i++) {
u32 val = tegra_spdif_read(spdif, regs[i].offset);
seq_printf(s, "%s = %08x\n", regs[i].name, val);
}
return 0;
}
static int tegra_spdif_debug_open(struct inode *inode, struct file *file)
{
return single_open(file, tegra_spdif_show, inode->i_private);
}
static const struct file_operations tegra_spdif_debug_fops = {
.open = tegra_spdif_debug_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static void tegra_spdif_debug_add(struct tegra_spdif *spdif)
{
spdif->debug = debugfs_create_file(DRV_NAME, S_IRUGO,
snd_soc_debugfs_root, spdif,
&tegra_spdif_debug_fops);
}
static void tegra_spdif_debug_remove(struct tegra_spdif *spdif)
{
if (spdif->debug)
debugfs_remove(spdif->debug);
}
#else
static inline void tegra_spdif_debug_add(struct tegra_spdif *spdif)
{
}
static inline void tegra_spdif_debug_remove(struct tegra_spdif *spdif)
{
}
#endif
static int tegra_spdif_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
struct device *dev = substream->pcm->card->dev;
struct tegra_spdif *spdif = snd_soc_dai_get_drvdata(dai);
int ret, srate, spdifclock;
spdif->reg_ctrl &= ~TEGRA_SPDIF_CTRL_PACK;
spdif->reg_ctrl &= ~TEGRA_SPDIF_CTRL_BIT_MODE_MASK;
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
spdif->reg_ctrl |= TEGRA_SPDIF_CTRL_PACK;
spdif->reg_ctrl |= TEGRA_SPDIF_CTRL_BIT_MODE_16BIT;
break;
default:
return -EINVAL;
}
srate = params_rate(params);
switch (params_rate(params)) {
case 32000:
spdifclock = 4096000;
break;
case 44100:
spdifclock = 5644800;
break;
case 48000:
spdifclock = 6144000;
break;
case 88200:
spdifclock = 11289600;
break;
case 96000:
spdifclock = 12288000;
break;
case 176400:
spdifclock = 22579200;
break;
case 192000:
spdifclock = 24576000;
break;
default:
return -EINVAL;
}
ret = clk_set_rate(spdif->clk_spdif_out, spdifclock);
if (ret) {
dev_err(dev, "Can't set SPDIF clock rate: %d\n", ret);
return ret;
}
return 0;
}
static void tegra_spdif_start_playback(struct tegra_spdif *spdif)
{
spdif->reg_ctrl |= TEGRA_SPDIF_CTRL_TX_EN;
tegra_spdif_write(spdif, TEGRA_SPDIF_CTRL, spdif->reg_ctrl);
}
static void tegra_spdif_stop_playback(struct tegra_spdif *spdif)
{
spdif->reg_ctrl &= ~TEGRA_SPDIF_CTRL_TX_EN;
tegra_spdif_write(spdif, TEGRA_SPDIF_CTRL, spdif->reg_ctrl);
}
static int tegra_spdif_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *dai)
{
struct tegra_spdif *spdif = snd_soc_dai_get_drvdata(dai);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
case SNDRV_PCM_TRIGGER_RESUME:
if (!spdif->clk_refs)
clk_enable(spdif->clk_spdif_out);
spdif->clk_refs++;
tegra_spdif_start_playback(spdif);
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
case SNDRV_PCM_TRIGGER_SUSPEND:
tegra_spdif_stop_playback(spdif);
spdif->clk_refs--;
if (!spdif->clk_refs)
clk_disable(spdif->clk_spdif_out);
break;
default:
return -EINVAL;
}
return 0;
}
static int tegra_spdif_probe(struct snd_soc_dai *dai)
{
struct tegra_spdif *spdif = snd_soc_dai_get_drvdata(dai);
dai->capture_dma_data = NULL;
dai->playback_dma_data = &spdif->playback_dma_data;
return 0;
}
static struct snd_soc_dai_ops tegra_spdif_dai_ops = {
.hw_params = tegra_spdif_hw_params,
.trigger = tegra_spdif_trigger,
};
struct snd_soc_dai_driver tegra_spdif_dai = {
.name = DRV_NAME,
.probe = tegra_spdif_probe,
.playback = {
.channels_min = 2,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
SNDRV_PCM_RATE_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
},
.ops = &tegra_spdif_dai_ops,
};
static __devinit int tegra_spdif_platform_probe(struct platform_device *pdev)
{
struct tegra_spdif *spdif;
struct resource *mem, *memregion, *dmareq;
int ret;
spdif = kzalloc(sizeof(struct tegra_spdif), GFP_KERNEL);
if (!spdif) {
dev_err(&pdev->dev, "Can't allocate tegra_spdif\n");
ret = -ENOMEM;
goto exit;
}
dev_set_drvdata(&pdev->dev, spdif);
spdif->clk_spdif_out = clk_get(&pdev->dev, "spdif_out");
if (IS_ERR(spdif->clk_spdif_out)) {
pr_err("Can't retrieve spdif clock\n");
ret = PTR_ERR(spdif->clk_spdif_out);
goto err_free;
}
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!mem) {
dev_err(&pdev->dev, "No memory resource\n");
ret = -ENODEV;
goto err_clk_put;
}
dmareq = platform_get_resource(pdev, IORESOURCE_DMA, 0);
if (!dmareq) {
dev_err(&pdev->dev, "No DMA resource\n");
ret = -ENODEV;
goto err_clk_put;
}
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_clk_put;
}
spdif->regs = ioremap(mem->start, resource_size(mem));
if (!spdif->regs) {
dev_err(&pdev->dev, "ioremap failed\n");
ret = -ENOMEM;
goto err_release;
}
spdif->playback_dma_data.addr = mem->start + TEGRA_SPDIF_DATA_OUT;
spdif->playback_dma_data.wrap = 4;
spdif->playback_dma_data.width = 32;
spdif->playback_dma_data.req_sel = dmareq->start;
ret = snd_soc_register_dai(&pdev->dev, &tegra_spdif_dai);
if (ret) {
dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
ret = -ENOMEM;
goto err_unmap;
}
tegra_spdif_debug_add(spdif);
return 0;
err_unmap:
iounmap(spdif->regs);
err_release:
release_mem_region(mem->start, resource_size(mem));
err_clk_put:
clk_put(spdif->clk_spdif_out);
err_free:
kfree(spdif);
exit:
return ret;
}
static int __devexit tegra_spdif_platform_remove(struct platform_device *pdev)
{
struct tegra_spdif *spdif = dev_get_drvdata(&pdev->dev);
struct resource *res;
snd_soc_unregister_dai(&pdev->dev);
tegra_spdif_debug_remove(spdif);
iounmap(spdif->regs);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(res->start, resource_size(res));
clk_put(spdif->clk_spdif_out);
kfree(spdif);
return 0;
}
static struct platform_driver tegra_spdif_driver = {
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
},
.probe = tegra_spdif_platform_probe,
.remove = __devexit_p(tegra_spdif_platform_remove),
};
static int __init snd_tegra_spdif_init(void)
{
return platform_driver_register(&tegra_spdif_driver);
}
module_init(snd_tegra_spdif_init);
static void __exit snd_tegra_spdif_exit(void)
{
platform_driver_unregister(&tegra_spdif_driver);
}
module_exit(snd_tegra_spdif_exit);
MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
MODULE_DESCRIPTION("Tegra SPDIF ASoC driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRV_NAME);

View file

@ -0,0 +1,473 @@
/*
* tegra_spdif.h - Definitions for Tegra SPDIF driver
*
* Author: Stephen Warren <swarren@nvidia.com>
* Copyright (C) 2011 - NVIDIA, Inc.
*
* Based on code copyright/by:
* Copyright (c) 2008-2009, NVIDIA Corporation
*
* 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_SPDIF_H__
#define __TEGRA_SPDIF_H__
#include "tegra_pcm.h"
/* Offsets from TEGRA_SPDIF_BASE */
#define TEGRA_SPDIF_CTRL 0x0
#define TEGRA_SPDIF_STATUS 0x4
#define TEGRA_SPDIF_STROBE_CTRL 0x8
#define TEGRA_SPDIF_DATA_FIFO_CSR 0x0C
#define TEGRA_SPDIF_DATA_OUT 0x40
#define TEGRA_SPDIF_DATA_IN 0x80
#define TEGRA_SPDIF_CH_STA_RX_A 0x100
#define TEGRA_SPDIF_CH_STA_RX_B 0x104
#define TEGRA_SPDIF_CH_STA_RX_C 0x108
#define TEGRA_SPDIF_CH_STA_RX_D 0x10C
#define TEGRA_SPDIF_CH_STA_RX_E 0x110
#define TEGRA_SPDIF_CH_STA_RX_F 0x114
#define TEGRA_SPDIF_CH_STA_TX_A 0x140
#define TEGRA_SPDIF_CH_STA_TX_B 0x144
#define TEGRA_SPDIF_CH_STA_TX_C 0x148
#define TEGRA_SPDIF_CH_STA_TX_D 0x14C
#define TEGRA_SPDIF_CH_STA_TX_E 0x150
#define TEGRA_SPDIF_CH_STA_TX_F 0x154
#define TEGRA_SPDIF_USR_STA_RX_A 0x180
#define TEGRA_SPDIF_USR_DAT_TX_A 0x1C0
/* Fields in TEGRA_SPDIF_CTRL */
/* Start capturing from 0=right, 1=left channel */
#define TEGRA_SPDIF_CTRL_CAP_LC (1 << 30)
/* SPDIF receiver(RX) enable */
#define TEGRA_SPDIF_CTRL_RX_EN (1 << 29)
/* SPDIF Transmitter(TX) enable */
#define TEGRA_SPDIF_CTRL_TX_EN (1 << 28)
/* Transmit Channel status */
#define TEGRA_SPDIF_CTRL_TC_EN (1 << 27)
/* Transmit user Data */
#define TEGRA_SPDIF_CTRL_TU_EN (1 << 26)
/* Interrupt on transmit error */
#define TEGRA_SPDIF_CTRL_IE_TXE (1 << 25)
/* Interrupt on receive error */
#define TEGRA_SPDIF_CTRL_IE_RXE (1 << 24)
/* Interrupt on invalid preamble */
#define TEGRA_SPDIF_CTRL_IE_P (1 << 23)
/* Interrupt on "B" preamble */
#define TEGRA_SPDIF_CTRL_IE_B (1 << 22)
/* Interrupt when block of channel status received */
#define TEGRA_SPDIF_CTRL_IE_C (1 << 21)
/* Interrupt when a valid information unit (IU) is received */
#define TEGRA_SPDIF_CTRL_IE_U (1 << 20)
/* Interrupt when RX user FIFO attention level is reached */
#define TEGRA_SPDIF_CTRL_QE_RU (1 << 19)
/* Interrupt when TX user FIFO attention level is reached */
#define TEGRA_SPDIF_CTRL_QE_TU (1 << 18)
/* Interrupt when RX data FIFO attention level is reached */
#define TEGRA_SPDIF_CTRL_QE_RX (1 << 17)
/* Interrupt when TX data FIFO attention level is reached */
#define TEGRA_SPDIF_CTRL_QE_TX (1 << 16)
/* Loopback test mode enable */
#define TEGRA_SPDIF_CTRL_LBK_EN (1 << 15)
/*
* Pack data mode:
* 0 = Single data (16 bit needs to be padded to match the
* interface data bit size).
* 1 = Packeted left/right channel data into a single word.
*/
#define TEGRA_SPDIF_CTRL_PACK (1 << 14)
/*
* 00 = 16bit data
* 01 = 20bit data
* 10 = 24bit data
* 11 = raw data
*/
#define TEGRA_SPDIF_BIT_MODE_16BIT 0
#define TEGRA_SPDIF_BIT_MODE_20BIT 1
#define TEGRA_SPDIF_BIT_MODE_24BIT 2
#define TEGRA_SPDIF_BIT_MODE_RAW 3
#define TEGRA_SPDIF_CTRL_BIT_MODE_SHIFT 12
#define TEGRA_SPDIF_CTRL_BIT_MODE_MASK (3 << TEGRA_SPDIF_CTRL_BIT_MODE_SHIFT)
#define TEGRA_SPDIF_CTRL_BIT_MODE_16BIT (TEGRA_SPDIF_BIT_MODE_16BIT << TEGRA_SPDIF_CTRL_BIT_MODE_SHIFT)
#define TEGRA_SPDIF_CTRL_BIT_MODE_20BIT (TEGRA_SPDIF_BIT_MODE_20BIT << TEGRA_SPDIF_CTRL_BIT_MODE_SHIFT)
#define TEGRA_SPDIF_CTRL_BIT_MODE_24BIT (TEGRA_SPDIF_BIT_MODE_24BIT << TEGRA_SPDIF_CTRL_BIT_MODE_SHIFT)
#define TEGRA_SPDIF_CTRL_BIT_MODE_RAW (TEGRA_SPDIF_BIT_MODE_RAW << TEGRA_SPDIF_CTRL_BIT_MODE_SHIFT)
/* Fields in TEGRA_SPDIF_STATUS */
/*
* Note: IS_P, IS_B, IS_C, and IS_U are sticky bits. Software must
* write a 1 to the corresponding bit location to clear the status.
*/
/*
* Receiver(RX) shifter is busy receiving data.
* This bit is asserted when the receiver first locked onto the
* preamble of the data stream after RX_EN is asserted. This bit is
* deasserted when either,
* (a) the end of a frame is reached after RX_EN is deeasserted, or
* (b) the SPDIF data stream becomes inactive.
*/
#define TEGRA_SPDIF_STATUS_RX_BSY (1 << 29)
/*
* Transmitter(TX) shifter is busy transmitting data.
* This bit is asserted when TX_EN is asserted.
* This bit is deasserted when the end of a frame is reached after
* TX_EN is deasserted.
*/
#define TEGRA_SPDIF_STATUS_TX_BSY (1 << 28)
/*
* TX is busy shifting out channel status.
* This bit is asserted when both TX_EN and TC_EN are asserted and
* data from CH_STA_TX_A register is loaded into the internal shifter.
* This bit is deasserted when either,
* (a) the end of a frame is reached after TX_EN is deasserted, or
* (b) CH_STA_TX_F register is loaded into the internal shifter.
*/
#define TEGRA_SPDIF_STATUS_TC_BSY (1 << 27)
/*
* TX User data FIFO busy.
* This bit is asserted when TX_EN and TXU_EN are asserted and
* there's data in the TX user FIFO. This bit is deassert when either,
* (a) the end of a frame is reached after TX_EN is deasserted, or
* (b) there's no data left in the TX user FIFO.
*/
#define TEGRA_SPDIF_STATUS_TU_BSY (1 << 26)
/* TX FIFO Underrun error status */
#define TEGRA_SPDIF_STATUS_TX_ERR (1 << 25)
/* RX FIFO Overrun error status */
#define TEGRA_SPDIF_STATUS_RX_ERR (1 << 24)
/* Preamble status: 0=Preamble OK, 1=bad/missing preamble */
#define TEGRA_SPDIF_STATUS_IS_P (1 << 23)
/* B-preamble detection status: 0=not detected, 1=B-preamble detected */
#define TEGRA_SPDIF_STATUS_IS_B (1 << 22)
/*
* RX channel block data receive status:
* 0=entire block not recieved yet.
* 1=received entire block of channel status,
*/
#define TEGRA_SPDIF_STATUS_IS_C (1 << 21)
/* RX User Data Valid flag: 1=valid IU detected, 0 = no IU detected. */
#define TEGRA_SPDIF_STATUS_IS_U (1 << 20)
/*
* RX User FIFO Status:
* 1=attention level reached, 0=attention level not reached.
*/
#define TEGRA_SPDIF_STATUS_QS_RU (1 << 19)
/*
* TX User FIFO Status:
* 1=attention level reached, 0=attention level not reached.
*/
#define TEGRA_SPDIF_STATUS_QS_TU (1 << 18)
/*
* RX Data FIFO Status:
* 1=attention level reached, 0=attention level not reached.
*/
#define TEGRA_SPDIF_STATUS_QS_RX (1 << 17)
/*
* TX Data FIFO Status:
* 1=attention level reached, 0=attention level not reached.
*/
#define TEGRA_SPDIF_STATUS_QS_TX (1 << 16)
/* Fields in TEGRA_SPDIF_STROBE_CTRL */
/*
* Indicates the approximate number of detected SPDIFIN clocks within a
* bi-phase period.
*/
#define TEGRA_SPDIF_STROBE_CTRL_PERIOD_SHIFT 16
#define TEGRA_SPDIF_STROBE_CTRL_PERIOD_MASK (0xff << TEGRA_SPDIF_STROBE_CTRL_PERIOD_SHIFT)
/* Data strobe mode: 0=Auto-locked 1=Manual locked */
#define TEGRA_SPDIF_STROBE_CTRL_STROBE (1 << 15)
/*
* Manual data strobe time within the bi-phase clock period (in terms of
* the number of over-sampling clocks).
*/
#define TEGRA_SPDIF_STROBE_CTRL_DATA_STROBES_SHIFT 8
#define TEGRA_SPDIF_STROBE_CTRL_DATA_STROBES_MASK (0x1f << TEGRA_SPDIF_STROBE_CTRL_DATA_STROBES_SHIFT)
/*
* Manual SPDIFIN bi-phase clock period (in terms of the number of
* over-sampling clocks).
*/
#define TEGRA_SPDIF_STROBE_CTRL_CLOCK_PERIOD_SHIFT 0
#define TEGRA_SPDIF_STROBE_CTRL_CLOCK_PERIOD_MASK (0x3f << TEGRA_SPDIF_STROBE_CTRL_CLOCK_PERIOD_SHIFT)
/* Fields in SPDIF_DATA_FIFO_CSR */
/* Clear Receiver User FIFO (RX USR.FIFO) */
#define TEGRA_SPDIF_DATA_FIFO_CSR_RU_CLR (1 << 31)
#define TEGRA_SPDIF_FIFO_ATN_LVL_U_ONE_SLOT 0
#define TEGRA_SPDIF_FIFO_ATN_LVL_U_TWO_SLOTS 1
#define TEGRA_SPDIF_FIFO_ATN_LVL_U_THREE_SLOTS 2
#define TEGRA_SPDIF_FIFO_ATN_LVL_U_FOUR_SLOTS 3
/* RU FIFO attention level */
#define TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_SHIFT 29
#define TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_MASK \
(0x3 << TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_SHIFT)
#define TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_RU1_WORD_FULL \
(TEGRA_SPDIF_FIFO_ATN_LVL_U_ONE_SLOT << TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_SHIFT)
#define TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_RU2_WORD_FULL \
(TEGRA_SPDIF_FIFO_ATN_LVL_U_TWO_SLOTS << TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_SHIFT)
#define TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_RU3_WORD_FULL \
(TEGRA_SPDIF_FIFO_ATN_LVL_U_THREE_SLOTS << TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_SHIFT)
#define TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_RU4_WORD_FULL \
(TEGRA_SPDIF_FIFO_ATN_LVL_U_FOUR_SLOTS << TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_SHIFT)
/* Number of RX USR.FIFO levels with valid data. */
#define TEGRA_SPDIF_DATA_FIFO_CSR_RU_FULL_COUNT_SHIFT 24
#define TEGRA_SPDIF_DATA_FIFO_CSR_RU_FULL_COUNT_MASK (0x1f << TEGRA_SPDIF_DATA_FIFO_CSR_RU_FULL_COUNT_SHIFT)
/* Clear Transmitter User FIFO (TX USR.FIFO) */
#define TEGRA_SPDIF_DATA_FIFO_CSR_TU_CLR (1 << 23)
/* TU FIFO attention level */
#define TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_SHIFT 21
#define TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_MASK \
(0x3 << TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_SHIFT)
#define TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_TU1_WORD_FULL \
(TEGRA_SPDIF_FIFO_ATN_LVL_U_ONE_SLOT << TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_SHIFT)
#define TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_TU2_WORD_FULL \
(TEGRA_SPDIF_FIFO_ATN_LVL_U_TWO_SLOTS << TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_SHIFT)
#define TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_TU3_WORD_FULL \
(TEGRA_SPDIF_FIFO_ATN_LVL_U_THREE_SLOTS << TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_SHIFT)
#define TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_TU4_WORD_FULL \
(TEGRA_SPDIF_FIFO_ATN_LVL_U_FOUR_SLOTS << TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_SHIFT)
/* Number of TX USR.FIFO levels that could be filled. */
#define TEGRA_SPDIF_DATA_FIFO_CSR_TU_EMPTY_COUNT_SHIFT 16
#define TEGRA_SPDIF_DATA_FIFO_CSR_TU_EMPTY_COUNT_MASK (0x1f << SPDIF_DATA_FIFO_CSR_TU_EMPTY_COUNT_SHIFT)
/* Clear Receiver Data FIFO (RX DATA.FIFO) */
#define TEGRA_SPDIF_DATA_FIFO_CSR_RX_CLR (1 << 15)
#define TEGRA_SPDIF_FIFO_ATN_LVL_D_ONE_SLOT 0
#define TEGRA_SPDIF_FIFO_ATN_LVL_D_FOUR_SLOTS 1
#define TEGRA_SPDIF_FIFO_ATN_LVL_D_EIGHT_SLOTS 2
#define TEGRA_SPDIF_FIFO_ATN_LVL_D_TWELVE_SLOTS 3
/* RU FIFO attention level */
#define TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_SHIFT 13
#define TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_MASK \
(0x3 << TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_SHIFT)
#define TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_RU1_WORD_FULL \
(TEGRA_SPDIF_FIFO_ATN_LVL_D_ONE_SLOT << TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_SHIFT)
#define TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_RU4_WORD_FULL \
(TEGRA_SPDIF_FIFO_ATN_LVL_D_FOUR_SLOTS << TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_SHIFT)
#define TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_RU8_WORD_FULL \
(TEGRA_SPDIF_FIFO_ATN_LVL_D_EIGHT_SLOTS << TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_SHIFT)
#define TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_RU12_WORD_FULL \
(TEGRA_SPDIF_FIFO_ATN_LVL_D_TWELVE_SLOTS << TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_SHIFT)
/* Number of RX DATA.FIFO levels with valid data. */
#define TEGRA_SPDIF_DATA_FIFO_CSR_RX_FULL_COUNT_SHIFT 8
#define TEGRA_SPDIF_DATA_FIFO_CSR_RX_FULL_COUNT_MASK (0x1f << TEGRA_SPDIF_DATA_FIFO_CSR_RX_FULL_COUNT_SHIFT)
/* Clear Transmitter Data FIFO (TX DATA.FIFO) */
#define TEGRA_SPDIF_DATA_FIFO_CSR_TX_CLR (1 << 7)
/* TU FIFO attention level */
#define TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_SHIFT 5
#define TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_MASK \
(0x3 << TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_SHIFT)
#define TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_TU1_WORD_FULL \
(TEGRA_SPDIF_FIFO_ATN_LVL_D_ONE_SLOT << TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_SHIFT)
#define TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_TU4_WORD_FULL \
(TEGRA_SPDIF_FIFO_ATN_LVL_D_FOUR_SLOTS << TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_SHIFT)
#define TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_TU8_WORD_FULL \
(TEGRA_SPDIF_FIFO_ATN_LVL_D_EIGHT_SLOTS << TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_SHIFT)
#define TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_TU12_WORD_FULL \
(TEGRA_SPDIF_FIFO_ATN_LVL_D_TWELVE_SLOTS << TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_SHIFT)
/* Number of TX DATA.FIFO levels that could be filled. */
#define TEGRA_SPDIF_DATA_FIFO_CSR_TX_EMPTY_COUNT_SHIFT 0
#define TEGRA_SPDIF_DATA_FIFO_CSR_TX_EMPTY_COUNT_MASK (0x1f << SPDIF_DATA_FIFO_CSR_TX_EMPTY_COUNT_SHIFT)
/* Fields in TEGRA_SPDIF_DATA_OUT */
/*
* This register has 5 different formats:
* 16-bit (BIT_MODE=00, PACK=0)
* 20-bit (BIT_MODE=01, PACK=0)
* 24-bit (BIT_MODE=10, PACK=0)
* raw (BIT_MODE=11, PACK=0)
* 16-bit packed (BIT_MODE=00, PACK=1)
*/
#define TEGRA_SPDIF_DATA_OUT_DATA_16_SHIFT 0
#define TEGRA_SPDIF_DATA_OUT_DATA_16_MASK (0xffff << TEGRA_SPDIF_DATA_OUT_DATA_16_SHIFT)
#define TEGRA_SPDIF_DATA_OUT_DATA_20_SHIFT 0
#define TEGRA_SPDIF_DATA_OUT_DATA_20_MASK (0xfffff << TEGRA_SPDIF_DATA_OUT_DATA_20_SHIFT)
#define TEGRA_SPDIF_DATA_OUT_DATA_24_SHIFT 0
#define TEGRA_SPDIF_DATA_OUT_DATA_24_MASK (0xffffff << TEGRA_SPDIF_DATA_OUT_DATA_24_SHIFT)
#define TEGRA_SPDIF_DATA_OUT_DATA_RAW_P (1 << 31)
#define TEGRA_SPDIF_DATA_OUT_DATA_RAW_C (1 << 30)
#define TEGRA_SPDIF_DATA_OUT_DATA_RAW_U (1 << 29)
#define TEGRA_SPDIF_DATA_OUT_DATA_RAW_V (1 << 28)
#define TEGRA_SPDIF_DATA_OUT_DATA_RAW_DATA_SHIFT 8
#define TEGRA_SPDIF_DATA_OUT_DATA_RAW_DATA_MASK (0xfffff << TEGRA_SPDIF_DATA_OUT_DATA_RAW_DATA_SHIFT)
#define TEGRA_SPDIF_DATA_OUT_DATA_RAW_AUX_SHIFT 4
#define TEGRA_SPDIF_DATA_OUT_DATA_RAW_AUX_MASK (0xf << TEGRA_SPDIF_DATA_OUT_DATA_RAW_AUX_SHIFT)
#define TEGRA_SPDIF_DATA_OUT_DATA_RAW_PREAMBLE_SHIFT 0
#define TEGRA_SPDIF_DATA_OUT_DATA_RAW_PREAMBLE_MASK (0xf << TEGRA_SPDIF_DATA_OUT_DATA_RAW_PREAMBLE_SHIFT)
#define TEGRA_SPDIF_DATA_OUT_DATA_16_PACKED_RIGHT_SHIFT 16
#define TEGRA_SPDIF_DATA_OUT_DATA_16_PACKED_RIGHT_MASK (0xffff << TEGRA_SPDIF_DATA_OUT_DATA_16_PACKED_RIGHT_SHIFT)
#define TEGRA_SPDIF_DATA_OUT_DATA_16_PACKED_LEFT_SHIFT 0
#define TEGRA_SPDIF_DATA_OUT_DATA_16_PACKED_LEFT_MASK (0xffff << TEGRA_SPDIF_DATA_OUT_DATA_16_PACKED_LEFT_SHIFT)
/* Fields in TEGRA_SPDIF_DATA_IN */
/*
* This register has 5 different formats:
* 16-bit (BIT_MODE=00, PACK=0)
* 20-bit (BIT_MODE=01, PACK=0)
* 24-bit (BIT_MODE=10, PACK=0)
* raw (BIT_MODE=11, PACK=0)
* 16-bit packed (BIT_MODE=00, PACK=1)
*
* Bits 31:24 are common to all modes except 16-bit packed
*/
#define TEGRA_SPDIF_DATA_IN_DATA_P (1 << 31)
#define TEGRA_SPDIF_DATA_IN_DATA_C (1 << 30)
#define TEGRA_SPDIF_DATA_IN_DATA_U (1 << 29)
#define TEGRA_SPDIF_DATA_IN_DATA_V (1 << 28)
#define TEGRA_SPDIF_DATA_IN_DATA_PREAMBLE_SHIFT 24
#define TEGRA_SPDIF_DATA_IN_DATA_PREAMBLE_MASK (0xf << TEGRA_SPDIF_DATA_IN_DATA_PREAMBLE_SHIFT)
#define TEGRA_SPDIF_DATA_IN_DATA_16_SHIFT 0
#define TEGRA_SPDIF_DATA_IN_DATA_16_MASK (0xffff << TEGRA_SPDIF_DATA_IN_DATA_16_SHIFT)
#define TEGRA_SPDIF_DATA_IN_DATA_20_SHIFT 0
#define TEGRA_SPDIF_DATA_IN_DATA_20_MASK (0xfffff << TEGRA_SPDIF_DATA_IN_DATA_20_SHIFT)
#define TEGRA_SPDIF_DATA_IN_DATA_24_SHIFT 0
#define TEGRA_SPDIF_DATA_IN_DATA_24_MASK (0xffffff << TEGRA_SPDIF_DATA_IN_DATA_24_SHIFT)
#define TEGRA_SPDIF_DATA_IN_DATA_RAW_DATA_SHIFT 8
#define TEGRA_SPDIF_DATA_IN_DATA_RAW_DATA_MASK (0xfffff << TEGRA_SPDIF_DATA_IN_DATA_RAW_DATA_SHIFT)
#define TEGRA_SPDIF_DATA_IN_DATA_RAW_AUX_SHIFT 4
#define TEGRA_SPDIF_DATA_IN_DATA_RAW_AUX_MASK (0xf << TEGRA_SPDIF_DATA_IN_DATA_RAW_AUX_SHIFT)
#define TEGRA_SPDIF_DATA_IN_DATA_RAW_PREAMBLE_SHIFT 0
#define TEGRA_SPDIF_DATA_IN_DATA_RAW_PREAMBLE_MASK (0xf << TEGRA_SPDIF_DATA_IN_DATA_RAW_PREAMBLE_SHIFT)
#define TEGRA_SPDIF_DATA_IN_DATA_16_PACKED_RIGHT_SHIFT 16
#define TEGRA_SPDIF_DATA_IN_DATA_16_PACKED_RIGHT_MASK (0xffff << TEGRA_SPDIF_DATA_IN_DATA_16_PACKED_RIGHT_SHIFT)
#define TEGRA_SPDIF_DATA_IN_DATA_16_PACKED_LEFT_SHIFT 0
#define TEGRA_SPDIF_DATA_IN_DATA_16_PACKED_LEFT_MASK (0xffff << TEGRA_SPDIF_DATA_IN_DATA_16_PACKED_LEFT_SHIFT)
/* Fields in TEGRA_SPDIF_CH_STA_RX_A */
/* Fields in TEGRA_SPDIF_CH_STA_RX_B */
/* Fields in TEGRA_SPDIF_CH_STA_RX_C */
/* Fields in TEGRA_SPDIF_CH_STA_RX_D */
/* Fields in TEGRA_SPDIF_CH_STA_RX_E */
/* Fields in TEGRA_SPDIF_CH_STA_RX_F */
/*
* The 6-word receive channel data page buffer holds a block (192 frames) of
* channel status information. The order of receive is from LSB to MSB
* bit, and from CH_STA_RX_A to CH_STA_RX_F then back to CH_STA_RX_A.
*/
/* Fields in TEGRA_SPDIF_CH_STA_TX_A */
/* Fields in TEGRA_SPDIF_CH_STA_TX_B */
/* Fields in TEGRA_SPDIF_CH_STA_TX_C */
/* Fields in TEGRA_SPDIF_CH_STA_TX_D */
/* Fields in TEGRA_SPDIF_CH_STA_TX_E */
/* Fields in TEGRA_SPDIF_CH_STA_TX_F */
/*
* The 6-word transmit channel data page buffer holds a block (192 frames) of
* channel status information. The order of transmission is from LSB to MSB
* bit, and from CH_STA_TX_A to CH_STA_TX_F then back to CH_STA_TX_A.
*/
/* Fields in TEGRA_SPDIF_USR_STA_RX_A */
/*
* This 4-word deep FIFO receives user FIFO field information. The order of
* receive is from LSB to MSB bit.
*/
/* Fields in TEGRA_SPDIF_USR_DAT_TX_A */
/*
* This 4-word deep FIFO transmits user FIFO field information. The order of
* transmission is from LSB to MSB bit.
*/
struct tegra_spdif {
struct clk *clk_spdif_out;
int clk_refs;
struct tegra_pcm_dma_params capture_dma_data;
struct tegra_pcm_dma_params playback_dma_data;
void __iomem *regs;
struct dentry *debug;
u32 reg_ctrl;
};
#endif