diff options
author | Wallace Wang <r59996@freescale.com> | 2009-11-26 16:00:05 +0800 |
---|---|---|
committer | Alejandro Gonzalez <alex.gonzalez@digi.com> | 2010-02-12 17:19:39 +0100 |
commit | 53931e582f219b987d5290d9ef9c81dd144665c3 (patch) | |
tree | f08c18fe7817f2d5857418428f606459c3993d66 /sound/soc | |
parent | 7afeb32abc2bf86d0790b6027d90991c193aff57 (diff) |
ENGR00118790 ASoC AC97 codec driver
Add ac97 mode support for SSI module
Signed-off-by: Wallace Wang <r59996@freescale.com>
Diffstat (limited to 'sound/soc')
-rw-r--r-- | sound/soc/imx/Kconfig | 3 | ||||
-rw-r--r-- | sound/soc/imx/Makefile | 2 | ||||
-rw-r--r-- | sound/soc/imx/imx-ac97.c | 564 | ||||
-rw-r--r-- | sound/soc/imx/imx-ssi.h | 22 |
4 files changed, 586 insertions, 5 deletions
diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig index 6f8e690044e2..c642782e1721 100644 --- a/sound/soc/imx/Kconfig +++ b/sound/soc/imx/Kconfig @@ -15,6 +15,9 @@ config SND_MXC_SOC_SSI config SND_MXC_SOC_ESAI tristate +config SND_MXC_SOC_AC97 + tristate + config SND_MXC_SOC_IRAM bool "Locate Audio DMA playback buffers in IRAM" help diff --git a/sound/soc/imx/Makefile b/sound/soc/imx/Makefile index 519377291202..d8cd279eb62b 100644 --- a/sound/soc/imx/Makefile +++ b/sound/soc/imx/Makefile @@ -2,10 +2,12 @@ snd-soc-imx-objs := imx-pcm.o snd-soc-imx-ssi-objs := imx-ssi.o snd-soc-imx-esai-objs := imx-esai.o +snd-soc-imx-ac97-objs := imx-ac97.o obj-$(CONFIG_SND_MXC_SOC) += snd-soc-imx.o obj-$(CONFIG_SND_MXC_SOC_SSI) += snd-soc-imx-ssi.o obj-$(CONFIG_SND_MXC_SOC_ESAI) += snd-soc-imx-esai.o +obj-$(CONFIG_SND_MXC_SOC_AC97) += snd-soc-imx-ac97.o # i.MX Machine Support snd-soc-imx-3stack-wm8350-objs := imx-3stack-wm8350.o diff --git a/sound/soc/imx/imx-ac97.c b/sound/soc/imx/imx-ac97.c new file mode 100644 index 000000000000..019e7f9a8fe8 --- /dev/null +++ b/sound/soc/imx/imx-ac97.c @@ -0,0 +1,564 @@ +/* + * imx-ac97.c -- AC97 driver for Freescale IMX + * + * + * Copyright 2009 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * Revision history + * 26th Nov. 2009 Initial version. + * + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/clk.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/core.h> +#include <sound/soc.h> +#include <mach/clock.h> +#include <mach/hardware.h> +#include <asm/mach-types.h> +#include <linux/delay.h> + +#include "imx-ssi.h" +#include "imx-pcm.h" + +static DEFINE_MUTEX(ac97_mutex); +static DECLARE_COMPLETION(ac97_completion); + +struct imx_ac97_runtime { + u32 id; + u32 playback; + u32 capture; +}; + +static struct imx_ac97_runtime imx_ac97_para; +static struct imx_ssi imx_ac97_data[2]; + +#define IMX_SSI_DUMP 0 +#if IMX_SSI_DUMP +#define SSI_DUMP() \ + do { \ + printk(KERN_INFO "dump @ %s\n", __func__); \ + printk(KERN_INFO "scr %x\t, %x\n", \ + __raw_readl(SSI1_SCR), __raw_readl(SSI2_SCR)); \ + printk(KERN_INFO "sisr %x\t, %x\n", \ + __raw_readl(SSI1_SISR), __raw_readl(SSI2_SISR)); \ + printk(KERN_INFO "stcr %x\t, %x\n", \ + __raw_readl(SSI1_STCR), __raw_readl(SSI2_STCR)); \ + printk(KERN_INFO "srcr %x\t, %x\n", \ + __raw_readl(SSI1_SRCR), __raw_readl(SSI2_SRCR)); \ + printk(KERN_INFO "stccr %x\t, %x\n", \ + __raw_readl(SSI1_STCCR), __raw_readl(SSI2_STCCR)); \ + printk(KERN_INFO "srccr %x\t, %x\n", \ + __raw_readl(SSI1_SRCCR), __raw_readl(SSI2_SRCCR)); \ + printk(KERN_INFO "sfcsr %x\t, %x\n", \ + __raw_readl(SSI1_SFCSR), __raw_readl(SSI2_SFCSR)); \ + printk(KERN_INFO "stmsk %x\t, %x\n", \ + __raw_readl(SSI1_STMSK), __raw_readl(SSI2_STMSK)); \ + printk(KERN_INFO "srmsk %x\t, %x\n", \ + __raw_readl(SSI1_SRMSK), __raw_readl(SSI2_SRMSK)); \ + printk(KERN_INFO "sier %x\t, %x\n", \ + __raw_readl(SSI1_SIER), __raw_readl(SSI2_SIER)); \ + printk(KERN_INFO "sacnt %x\t, %x\n", \ + __raw_readl(SSI1_SACNT), __raw_readl(SSI2_SACNT)); \ + printk(KERN_INFO "sacdd %x\t, %x\n", \ + __raw_readl(SSI1_SACADD), __raw_readl(SSI2_SACADD)); \ + printk(KERN_INFO "sacdat %x\t, %x\n", \ + __raw_readl(SSI1_SACDAT), __raw_readl(SSI2_SACDAT)); \ + printk(KERN_INFO "satag %x\t, %x\n", \ + __raw_readl(SSI1_SATAG), __raw_readl(SSI2_SATAG)); \ + printk(KERN_INFO "saccst %x\t, %x\n", \ + __raw_readl(SSI1_SACCST), __raw_readl(SSI2_SACCST)); \ + printk(KERN_INFO "saccen %x\t, %x\n", \ + __raw_readl(SSI1_SACCEN), __raw_readl(SSI2_SACCEN)); \ + printk(KERN_INFO "saccdis %x\t, %x\n", \ + __raw_readl(SSI1_SACCDIS), __raw_readl(SSI2_SACCDIS)); \ + } while (0); +#else +#define SSI_DUMP() +#endif + +/* + * Read register value from codec, the read command is sent from + * AC97 slot 2 - 3. The register value is sent back at slot 2 -3 + * in next RX frame. + */ +static unsigned short imx_ac97_read(struct snd_ac97 *ac97, unsigned short reg) +{ + u32 sacdat, sier, scr; + mutex_lock(&ac97_mutex); + if (imx_ac97_para.id == IMX_DAI_AC97_1) { + sier = __raw_readl(SSI1_SIER); + scr = __raw_readl(SSI1_SCR); + __raw_writel((reg << 12), SSI1_SACADD); + __raw_writel(sier | SSI_SIER_CMDDU_EN, SSI1_SIER); + __raw_writel(SSI_SACNT_RD | __raw_readl(SSI1_SACNT), + SSI1_SACNT); + __raw_writel(scr | SSI_SCR_TE | SSI_SCR_RE, SSI1_SCR); + wait_for_completion_timeout(&ac97_completion, HZ); + sacdat = __raw_readl(SSI1_SACDAT); + __raw_writel(sier, SSI1_SIER); + __raw_writel(scr, SSI1_SCR); + } else { + sier = __raw_readl(SSI2_SIER); + scr = __raw_readl(SSI2_SCR); + __raw_writel((reg << 12), SSI2_SACADD); + __raw_writel(sier | SSI_SIER_CMDDU_EN, SSI2_SIER); + __raw_writel(SSI_SACNT_RD | __raw_readl(SSI2_SACNT), + SSI2_SACNT); + __raw_writel(scr | SSI_SCR_TE | SSI_SCR_RE, SSI2_SCR); + wait_for_completion_timeout(&ac97_completion, HZ); + sacdat = __raw_readl(SSI2_SACDAT); + __raw_writel(sier, SSI2_SIER); + __raw_writel(scr, SSI2_SCR); + } + mutex_unlock(&ac97_mutex); + return (unsigned short)(sacdat >> 4); + +} + +/* + * This fucntion is used to send command to codec. + */ +static void imx_ac97_write(struct snd_ac97 *ac97, unsigned short reg, + unsigned short val) +{ + u32 scr; + mutex_lock(&ac97_mutex); + if (imx_ac97_para.id == IMX_DAI_AC97_1) { + scr = __raw_readl(SSI1_SCR); + __raw_writel(reg << 12, SSI1_SACADD); + __raw_writel(val << 4, SSI1_SACDAT); + __raw_writel(SSI_SACNT_WR | __raw_readl(SSI1_SACNT), + SSI1_SACNT); + __raw_writel(scr | SSI_SCR_TE | SSI_SCR_RE, SSI1_SCR); + udelay(100); + __raw_writel(scr, SSI1_SCR); + } else { + scr = __raw_readl(SSI2_SCR); + __raw_writel(reg << 12, SSI2_SACADD); + __raw_writel(val << 4, SSI2_SACDAT); + __raw_writel(SSI_SACNT_WR | __raw_readl(SSI2_SACNT), + SSI2_SACNT); + __raw_writel(scr | SSI_SCR_TE | SSI_SCR_RE, SSI2_SCR); + udelay(100); + __raw_writel(scr, SSI1_SCR); + } + mutex_unlock(&ac97_mutex); + +} + +struct snd_ac97_bus_ops soc_ac97_ops = { + .read = imx_ac97_read, + .write = imx_ac97_write, +}; +EXPORT_SYMBOL_GPL(soc_ac97_ops); + +static struct clk *ssi1_clk; +static struct clk *ssi2_clk; + +static int imx_ac97_hw_tx_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *cpu_dai) +{ + struct imx_ssi *ssi_mode = (struct imx_ssi *)cpu_dai->private_data; + u32 channel = params_channels(params); + u32 stccr, sier; + + if (cpu_dai->id == IMX_DAI_AC97_1) { + stccr = + __raw_readl(SSI1_STCCR) & ~(SSI_STCCR_WL_MASK | + SSI_STCCR_DC_MASK); + sier = __raw_readl(SSI1_SIER); + } else { + stccr = + __raw_readl(SSI2_STCCR) & ~(SSI_STCCR_WL_MASK | + SSI_STCCR_DC_MASK); + sier = __raw_readl(SSI2_SIER); + } + + /* DAI data (word) size */ + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + stccr |= SSI_STCCR_WL(16) | SSI_STCCR_DC(0x0C); + break; + case SNDRV_PCM_FORMAT_S20_3LE: + stccr |= SSI_STCCR_WL(20) | SSI_STCCR_DC(0x0C); + break; + } + if (ssi_mode->ac97_rx_slots) + __raw_writel(ssi_mode->ac97_rx_slots, SSI1_SACCEN); + else + __raw_writel(((1 << channel) - 1) << (10 - channel), + SSI1_SACCEN); + + sier |= SSI_SIER_TDMAE; + + if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI1) { + __raw_writel(stccr, SSI1_STCCR); + __raw_writel(sier, SSI1_SIER); + } else { + __raw_writel(stccr, SSI2_STCCR); + __raw_writel(sier, SSI2_SIER); + } + + return 0; +} + +static int imx_ac97_hw_rx_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *cpu_dai) +{ + struct imx_ssi *ssi_mode = (struct imx_ssi *)cpu_dai->private_data; + u32 channel = params_channels(params); + u32 srccr, sier; + + if (cpu_dai->id == IMX_DAI_AC97_1) { + srccr = __raw_readl(SSI1_SRCCR); + sier = __raw_readl(SSI1_SIER); + } else { + srccr = __raw_readl(SSI2_SRCCR); + sier = __raw_readl(SSI2_SIER); + } + srccr &= ~(SSI_SRCCR_WL_MASK | SSI_SRCCR_DC_MASK); + + /* DAI data (word) size */ + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + srccr |= SSI_SRCCR_WL(16) | SSI_SRCCR_DC(0x0C); + break; + case SNDRV_PCM_FORMAT_S20_3LE: + srccr |= SSI_SRCCR_WL(20) | SSI_SRCCR_DC(0x0C); + break; + } + + if (ssi_mode->ac97_tx_slots) + __raw_writel(ssi_mode->ac97_tx_slots, SSI1_SACCEN); + else + __raw_writel(((1 << channel) - 1) << (10 - channel), + SSI1_SACCEN); + + /* enable interrupts */ + sier |= SSI_SIER_RDMAE; + + if (cpu_dai->id == IMX_DAI_AC97_1) { + __raw_writel(srccr, SSI1_SRCCR); + __raw_writel(sier, SSI1_SIER); + } else { + __raw_writel(srccr, SSI2_SRCCR); + __raw_writel(sier, SSI2_SIER); + } + return 0; +} + +static int imx_ac97_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *cpu_dai) +{ + u32 rate = params_rate(params); + u32 sacnt; + + if (cpu_dai->id == IMX_DAI_AC97_1) + sacnt = __raw_readl(SSI1_SACNT); + else + sacnt = __raw_readl(SSI2_SACNT); + + switch (rate) { + case 8000: + sacnt |= SSI_SACNT_FV | SSI_SACNT_FRDIV(0x05); + break; + case 11050: + sacnt |= SSI_SACNT_FV | SSI_SACNT_FRDIV(0x03); + break; + case 16000: + sacnt |= SSI_SACNT_FV | SSI_SACNT_FRDIV(0x02); + break; + case 22050: + sacnt |= SSI_SACNT_FV | SSI_SACNT_FRDIV(0x01); + break; + case 44100: + case 48000: + sacnt |= SSI_SACNT_FV | SSI_SACNT_FRDIV(0x00); + break; + } + + if (cpu_dai->id == IMX_DAI_AC97_1) + __raw_writel(sacnt, SSI1_SACNT); + else + __raw_writel(sacnt, SSI2_SACNT); + + /* Tx/Rx config */ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + return imx_ac97_hw_tx_params(substream, params, cpu_dai); + else + return imx_ac97_hw_rx_params(substream, params, cpu_dai); +} + +static int imx_ac97_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + u32 scr, i, reg; + + if (cpu_dai->id == IMX_DAI_AC97_1) + scr = __raw_readl(SSI1_SCR); + else + scr = __raw_readl(SSI2_SCR); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + for (i = 0; i < 12; i++) + __raw_writel(0x0, SSI1_STX0); + } else { + for (i = 0; i < 12; i++) + reg = __raw_readl(SSI1_SRX0); + } + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + imx_ac97_para.playback = 1; + else + imx_ac97_para.capture = 1; + scr |= SSI_SCR_TE | SSI_SCR_RE; + break; + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + imx_ac97_para.playback = 0; + else + imx_ac97_para.capture = 0; + + if ((imx_ac97_para.playback == 0) + && (imx_ac97_para.capture == 0)) + scr &= ~(SSI_SCR_TE | SSI_SCR_RE); + break; + default: + return -EINVAL; + } + if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI1) + __raw_writel(scr, SSI1_SCR); + else + __raw_writel(scr, SSI2_SCR); + SSI_DUMP(); + return 0; +} + +#ifdef CONFIG_PM +static int imx_ac97_suspend(struct snd_soc_dai *dai) +{ + if (!dai->active) + return 0; + + /* do we need to disable any clocks? */ + + return 0; +} + +static int imx_ac97_resume(struct snd_soc_dai *dai) +{ + if (!dai->active) + return 0; + + /* do we need to enable any clocks? */ + + return 0; +} +#else +#define imx_ac97_suspend NULL +#define imx_ac97_resume NULL +#endif + +static irqreturn_t ssi1_irq(int irq, void *dev_id) +{ + u32 sier, sisr, reg; + sier = __raw_readl(SSI1_SIER); + sisr = __raw_readl(SSI1_SISR); + if ((sier & SSI_SIER_CMDDU_EN) && (sisr & SSI_SISR_CMDDU)) { + reg = __raw_readl(SSI1_SACADD); + reg = __raw_readl(SSI1_SACDAT); + complete(&ac97_completion); + } + return IRQ_HANDLED; +} + +static irqreturn_t ssi2_irq(int irq, void *dev_id) +{ + u32 sier, sisr, reg; + sier = __raw_readl(SSI1_SIER); + sisr = __raw_readl(SSI1_SISR); + if ((sier & SSI_SIER_CMDDU_EN) && (sisr & SSI_SISR_CMDDU)) { + reg = __raw_readl(SSI2_SACADD); + reg = __raw_readl(SSI2_SACDAT); + complete(&ac97_completion); + } + return IRQ_HANDLED; +} + +static int imx_ac97_probe(struct platform_device *pdev, struct snd_soc_dai *dai) +{ + + u32 stccr; + stccr = SSI_STCCR_WL(16) | SSI_STCCR_DC(0x0C); + + if (!strcmp(dai->name, "imx-ac97-1")) { + dai->id = IMX_DAI_AC97_1; + ssi1_clk = clk_get(NULL, "ssi_clk.0"); + clk_enable(ssi1_clk); + + __raw_writel(SSI_SCR_SSIEN, SSI1_SCR); + + __raw_writel((SSI_SFCSR_RFWM1(SSI_RXFIFO_WATERMARK) | + SSI_SFCSR_RFWM0(SSI_RXFIFO_WATERMARK) | + SSI_SFCSR_TFWM1(SSI_TXFIFO_WATERMARK) | + SSI_SFCSR_TFWM0(SSI_TXFIFO_WATERMARK)), + SSI1_SFCSR); + + __raw_writel(stccr, SSI1_STCCR); + __raw_writel(stccr, SSI1_SRCCR); + __raw_writel(SSI_SACNT_AC97EN, SSI1_SACNT); + } else if (!strcmp(dai->name, "imx-ac97-2")) { + dai->id = IMX_DAI_AC97_2; + ssi2_clk = clk_get(NULL, "ssi_clk.1"); + clk_enable(ssi2_clk); + + __raw_writel(SSI_SCR_SSIEN, SSI2_SCR); + + __raw_writel((SSI_SFCSR_RFWM1(SSI_RXFIFO_WATERMARK) | + SSI_SFCSR_RFWM0(SSI_RXFIFO_WATERMARK) | + SSI_SFCSR_TFWM1(SSI_TXFIFO_WATERMARK) | + SSI_SFCSR_TFWM0(SSI_TXFIFO_WATERMARK)), + SSI2_SFCSR); + + __raw_writel(stccr, SSI2_STCCR); + __raw_writel(stccr, SSI2_SRCCR); + + __raw_writel(SSI_SACNT_AC97EN, SSI2_SACNT); + } else { + printk(KERN_ERR "%s: invalid device %s\n", __func__, dai->name); + return -ENODEV; + } + + if (!strcmp(dai->name, "imx-ac97-1")) { + if (request_irq(MXC_INT_SSI1, ssi1_irq, 0, "ssi1", dai)) { + printk(KERN_ERR + "%s: failure requesting irq %s\n", + __func__, "ssi1"); + return -EBUSY; + } + } + + if (!strcmp(dai->name, "imx-ac97-2")) { + if (request_irq(MXC_INT_SSI2, ssi2_irq, 0, "ssi2", dai)) { + printk(KERN_ERR + "%s: failure requesting irq %s\n", + __func__, "ssi2"); + return -EBUSY; + } + } + + return 0; +} + +static void imx_ac97_remove(struct platform_device *pdev, + struct snd_soc_dai *dai) +{ + if (!strcmp(dai->name, "imx-ac97-1")) + free_irq(MXC_INT_SSI1, dai); + + if (!strcmp(dai->name, "imx-ac97-2")) + free_irq(MXC_INT_SSI2, dai); +} + +#define IMX_AC97_RATES \ + (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | \ + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \ + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ + SNDRV_PCM_RATE_48000) + +#define IMX_AC97_FORMATS \ + (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE) + +static struct snd_soc_dai_ops imx_ac97_dai_ops = { + .hw_params = imx_ac97_hw_params, + .trigger = imx_ac97_trigger, +}; + +struct snd_soc_dai imx_ac97_dai[] = { + { + .name = "imx-ac97-1", + .id = 0, + .ac97_control = 1, + .probe = imx_ac97_probe, + .remove = imx_ac97_remove, + .suspend = imx_ac97_suspend, + .resume = imx_ac97_resume, + .playback = { + .stream_name = "AC97 Playback", + .channels_min = 1, + .channels_max = 10, + .rates = IMX_AC97_RATES, + .formats = IMX_AC97_FORMATS, + }, + .capture = { + .stream_name = "AC97 Capture", + .channels_min = 1, + .channels_max = 6, + .rates = IMX_AC97_RATES, + .formats = IMX_AC97_FORMATS, + }, + .ops = &imx_ac97_dai_ops, + .private_data = &imx_ac97_data[IMX_DAI_AC97_1], + }, + { + .name = "imx-ac97-2", + .id = 1, + .ac97_control = 1, + .probe = imx_ac97_probe, + .remove = imx_ac97_remove, + .suspend = imx_ac97_suspend, + .resume = imx_ac97_resume, + .playback = { + .stream_name = "AC97 Playback", + .channels_min = 1, + .channels_max = 10, + .rates = IMX_AC97_RATES, + .formats = IMX_AC97_FORMATS, + }, + .capture = { + .stream_name = "AC97 Capture", + .channels_min = 1, + .channels_max = 6, + .rates = IMX_AC97_RATES, + .formats = IMX_AC97_FORMATS, + }, + .ops = &imx_ac97_dai_ops, + .private_data = &imx_ac97_data[IMX_DAI_AC97_2], + }, +}; +EXPORT_SYMBOL_GPL(imx_ac97_dai); + +static int __init imx_ac97_init(void) +{ + return snd_soc_register_dais(imx_ac97_dai, ARRAY_SIZE(imx_ac97_dai)); +} + +static void __exit imx_ac97_exit(void) +{ + snd_soc_unregister_dais(imx_ac97_dai, ARRAY_SIZE(imx_ac97_dai)); +} + +module_init(imx_ac97_init); +module_exit(imx_ac97_exit); + +MODULE_DESCRIPTION("i.MX ASoC AC97 driver"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/imx/imx-ssi.h b/sound/soc/imx/imx-ssi.h index 387e992b397f..826386eb56ee 100644 --- a/sound/soc/imx/imx-ssi.h +++ b/sound/soc/imx/imx-ssi.h @@ -33,6 +33,9 @@ #define SSI1_SATAG ((SSI1_IO_BASE_ADDR) + 0x44) #define SSI1_STMSK ((SSI1_IO_BASE_ADDR) + 0x48) #define SSI1_SRMSK ((SSI1_IO_BASE_ADDR) + 0x4c) +#define SSI1_SACCST ((SSI1_IO_BASE_ADDR) + 0x50) +#define SSI1_SACCEN ((SSI1_IO_BASE_ADDR) + 0x54) +#define SSI1_SACCDIS ((SSI1_IO_BASE_ADDR) + 0x58) #define SSI2_STX0 ((SSI2_IO_BASE_ADDR) + 0x00) #define SSI2_STX1 ((SSI2_IO_BASE_ADDR) + 0x04) @@ -54,6 +57,9 @@ #define SSI2_SATAG ((SSI2_IO_BASE_ADDR) + 0x44) #define SSI2_STMSK ((SSI2_IO_BASE_ADDR) + 0x48) #define SSI2_SRMSK ((SSI2_IO_BASE_ADDR) + 0x4c) +#define SSI2_SACCST ((SSI2_IO_BASE_ADDR) + 0x50) +#define SSI2_SACCEN ((SSI2_IO_BASE_ADDR) + 0x54) +#define SSI2_SACCDIS ((SSI2_IO_BASE_ADDR) + 0x58) #define SSI_SCR_CLK_IST (1 << 9) #define SSI_SCR_TCH_EN (1 << 8) @@ -179,11 +185,11 @@ #define SSI_SOR_SYNRST (1 << 0) #define SSI_SACNT_FRDIV(x) (((x) & 0x3f) << 5) -#define SSI_SACNT_WR (x << 4) -#define SSI_SACNT_RD (x << 3) -#define SSI_SACNT_TIF (x << 2) -#define SSI_SACNT_FV (x << 1) -#define SSI_SACNT_AC97EN (x << 0) +#define SSI_SACNT_WR (1 << 4) +#define SSI_SACNT_RD (1 << 3) +#define SSI_SACNT_TIF (1 << 2) +#define SSI_SACNT_FV (1 << 1) +#define SSI_SACNT_AC97EN (1 << 0) /* SDMA & SSI watermarks for FIFO's */ #define SDMA_TXFIFO_WATERMARK 0x4 @@ -213,12 +219,18 @@ #define IMX_SSI_DIV_2_OFF (~SSI_STCCR_DIV2) #define IMX_SSI_DIV_2_ON SSI_STCCR_DIV2 +#define IMX_DAI_AC97_1 0 +#define IMX_DAI_AC97_2 1 + /* private info */ struct imx_ssi { bool network_mode; bool sync_mode; + unsigned int ac97_tx_slots; + unsigned int ac97_rx_slots; }; extern struct snd_soc_dai imx_ssi_dai[]; +extern struct snd_soc_dai imx_ac97_dai[]; #endif |