Commit 36b8a8bb authored by Frank Mandarino's avatar Frank Mandarino Committed by Jaroslav Kysela

[ALSA] ASoC AT91xxxx - SSC port DSP support

This patch series by Frank Madarino updates the AT91xxxx core to add
DSP/PCM audio hardware formats.
Changes:-
 o Rename at19-i2s.c -> at91-ssc.c
 o Rename at91-i2s.h -> at91-ssc.h
 o Add DSP hardware formats.
 o Rename various I2S labels to SSC
Signed-off-by: default avatarFrank Mandarino <fmandarino@endrelia.com>
Signed-off-by: default avatarLiam Girdwood <lg@opensource.wolfsonmicro.com>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
Signed-off-by: default avatarJaroslav Kysela <perex@suse.cz>
parent 1e39221e
/* /*
* at91-i2s.c -- ALSA SoC I2S Audio Layer Platform driver * at91-ssc.c -- ALSA SoC AT91 SSC Audio Layer Platform driver
* *
* Author: Frank Mandarino <fmandarino@endrelia.com> * Author: Frank Mandarino <fmandarino@endrelia.com>
* Endrelia Technologies Inc. * Endrelia Technologies Inc.
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <sound/driver.h> #include <sound/driver.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/pcm.h> #include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/initval.h> #include <sound/initval.h>
#include <sound/soc.h> #include <sound/soc.h>
...@@ -33,10 +34,10 @@ ...@@ -33,10 +34,10 @@
#include <asm/arch/at91_ssc.h> #include <asm/arch/at91_ssc.h>
#include "at91-pcm.h" #include "at91-pcm.h"
#include "at91-i2s.h" #include "at91-ssc.h"
#if 0 #if 0
#define DBG(x...) printk(KERN_DEBUG "at91-i2s:" x) #define DBG(x...) printk(KERN_DEBUG "at91-ssc:" x)
#else #else
#define DBG(x...) #define DBG(x...)
#endif #endif
...@@ -92,33 +93,33 @@ static struct at91_ssc_mask ssc_rx_mask = { ...@@ -92,33 +93,33 @@ static struct at91_ssc_mask ssc_rx_mask = {
*/ */
static struct at91_pcm_dma_params ssc_dma_params[NUM_SSC_DEVICES][2] = { static struct at91_pcm_dma_params ssc_dma_params[NUM_SSC_DEVICES][2] = {
{{ {{
.name = "SSC0/I2S PCM Stereo out", .name = "SSC0 PCM out",
.pdc = &pdc_tx_reg, .pdc = &pdc_tx_reg,
.mask = &ssc_tx_mask, .mask = &ssc_tx_mask,
}, },
{ {
.name = "SSC0/I2S PCM Stereo in", .name = "SSC0 PCM in",
.pdc = &pdc_rx_reg, .pdc = &pdc_rx_reg,
.mask = &ssc_rx_mask, .mask = &ssc_rx_mask,
}}, }},
#if NUM_SSC_DEVICES == 3 #if NUM_SSC_DEVICES == 3
{{ {{
.name = "SSC1/I2S PCM Stereo out", .name = "SSC1 PCM out",
.pdc = &pdc_tx_reg, .pdc = &pdc_tx_reg,
.mask = &ssc_tx_mask, .mask = &ssc_tx_mask,
}, },
{ {
.name = "SSC1/I2S PCM Stereo in", .name = "SSC1 PCM in",
.pdc = &pdc_rx_reg, .pdc = &pdc_rx_reg,
.mask = &ssc_rx_mask, .mask = &ssc_rx_mask,
}}, }},
{{ {{
.name = "SSC2/I2S PCM Stereo out", .name = "SSC2 PCM out",
.pdc = &pdc_tx_reg, .pdc = &pdc_tx_reg,
.mask = &ssc_tx_mask, .mask = &ssc_tx_mask,
}, },
{ {
.name = "SSC1/I2S PCM Stereo in", .name = "SSC2 PCM in",
.pdc = &pdc_rx_reg, .pdc = &pdc_rx_reg,
.mask = &ssc_rx_mask, .mask = &ssc_rx_mask,
}}, }},
...@@ -171,13 +172,13 @@ static struct at91_ssc_info { ...@@ -171,13 +172,13 @@ static struct at91_ssc_info {
#endif #endif
}; };
static unsigned int at91_i2s_sysclk; static unsigned int at91_ssc_sysclk;
/* /*
* SSC interrupt handler. Passes PDC interrupts to the DMA * SSC interrupt handler. Passes PDC interrupts to the DMA
* interrupt handler in the PCM driver. * interrupt handler in the PCM driver.
*/ */
static irqreturn_t at91_i2s_interrupt(int irq, void *dev_id) static irqreturn_t at91_ssc_interrupt(int irq, void *dev_id)
{ {
struct at91_ssc_info *ssc_p = dev_id; struct at91_ssc_info *ssc_p = dev_id;
struct at91_pcm_dma_params *dma_params; struct at91_pcm_dma_params *dma_params;
...@@ -209,13 +210,13 @@ static irqreturn_t at91_i2s_interrupt(int irq, void *dev_id) ...@@ -209,13 +210,13 @@ static irqreturn_t at91_i2s_interrupt(int irq, void *dev_id)
/* /*
* Startup. Only that one substream allowed in each direction. * Startup. Only that one substream allowed in each direction.
*/ */
static int at91_i2s_startup(struct snd_pcm_substream *substream) static int at91_ssc_startup(struct snd_pcm_substream *substream)
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id]; struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
int dir_mask; int dir_mask;
DBG("i2s_startup: SSC_SR=0x%08lx\n", DBG("ssc_startup: SSC_SR=0x%08lx\n",
at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR)); at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR));
dir_mask = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0x1 : 0x2; dir_mask = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0x1 : 0x2;
...@@ -234,7 +235,7 @@ static int at91_i2s_startup(struct snd_pcm_substream *substream) ...@@ -234,7 +235,7 @@ static int at91_i2s_startup(struct snd_pcm_substream *substream)
* Shutdown. Clear DMA parameters and shutdown the SSC if there * Shutdown. Clear DMA parameters and shutdown the SSC if there
* are no other substreams open. * are no other substreams open.
*/ */
static void at91_i2s_shutdown(struct snd_pcm_substream *substream) static void at91_ssc_shutdown(struct snd_pcm_substream *substream)
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id]; struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
...@@ -281,7 +282,7 @@ static void at91_i2s_shutdown(struct snd_pcm_substream *substream) ...@@ -281,7 +282,7 @@ static void at91_i2s_shutdown(struct snd_pcm_substream *substream)
/* /*
* Record the SSC system clock rate. * Record the SSC system clock rate.
*/ */
static int at91_i2s_set_dai_sysclk(struct snd_soc_cpu_dai *cpu_dai, static int at91_ssc_set_dai_sysclk(struct snd_soc_cpu_dai *cpu_dai,
int clk_id, unsigned int freq, int dir) int clk_id, unsigned int freq, int dir)
{ {
/* /*
...@@ -291,7 +292,7 @@ static int at91_i2s_set_dai_sysclk(struct snd_soc_cpu_dai *cpu_dai, ...@@ -291,7 +292,7 @@ static int at91_i2s_set_dai_sysclk(struct snd_soc_cpu_dai *cpu_dai,
*/ */
switch (clk_id) { switch (clk_id) {
case AT91_SYSCLK_MCK: case AT91_SYSCLK_MCK:
at91_i2s_sysclk = freq; at91_ssc_sysclk = freq;
break; break;
default: default:
return -EINVAL; return -EINVAL;
...@@ -303,14 +304,11 @@ static int at91_i2s_set_dai_sysclk(struct snd_soc_cpu_dai *cpu_dai, ...@@ -303,14 +304,11 @@ static int at91_i2s_set_dai_sysclk(struct snd_soc_cpu_dai *cpu_dai,
/* /*
* Record the DAI format for use in hw_params(). * Record the DAI format for use in hw_params().
*/ */
static int at91_i2s_set_dai_fmt(struct snd_soc_cpu_dai *cpu_dai, static int at91_ssc_set_dai_fmt(struct snd_soc_cpu_dai *cpu_dai,
unsigned int fmt) unsigned int fmt)
{ {
struct at91_ssc_info *ssc_p = &ssc_info[cpu_dai->id]; struct at91_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) != SND_SOC_DAIFMT_I2S)
return -EINVAL;
ssc_p->daifmt = fmt; ssc_p->daifmt = fmt;
return 0; return 0;
} }
...@@ -318,7 +316,7 @@ static int at91_i2s_set_dai_fmt(struct snd_soc_cpu_dai *cpu_dai, ...@@ -318,7 +316,7 @@ static int at91_i2s_set_dai_fmt(struct snd_soc_cpu_dai *cpu_dai,
/* /*
* Record SSC clock dividers for use in hw_params(). * Record SSC clock dividers for use in hw_params().
*/ */
static int at91_i2s_set_dai_clkdiv(struct snd_soc_cpu_dai *cpu_dai, static int at91_ssc_set_dai_clkdiv(struct snd_soc_cpu_dai *cpu_dai,
int div_id, int div) int div_id, int div)
{ {
struct at91_ssc_info *ssc_p = &ssc_info[cpu_dai->id]; struct at91_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
...@@ -355,7 +353,7 @@ static int at91_i2s_set_dai_clkdiv(struct snd_soc_cpu_dai *cpu_dai, ...@@ -355,7 +353,7 @@ static int at91_i2s_set_dai_clkdiv(struct snd_soc_cpu_dai *cpu_dai,
/* /*
* Configure the SSC. * Configure the SSC.
*/ */
static int at91_i2s_hw_params(struct snd_pcm_substream *substream, static int at91_ssc_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params) struct snd_pcm_hw_params *params)
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
...@@ -390,21 +388,51 @@ static int at91_i2s_hw_params(struct snd_pcm_substream *substream, ...@@ -390,21 +388,51 @@ static int at91_i2s_hw_params(struct snd_pcm_substream *substream,
channels = params_channels(params); channels = params_channels(params);
/*
* Determine sample size in bits and the PDC increment.
*/
switch(params_format(params)) {
case SNDRV_PCM_FORMAT_S8:
bits = 8;
dma_params->pdc_xfer_size = 1;
break;
case SNDRV_PCM_FORMAT_S16_LE:
bits = 16;
dma_params->pdc_xfer_size = 2;
break;
case SNDRV_PCM_FORMAT_S24_LE:
bits = 24;
dma_params->pdc_xfer_size = 4;
break;
case SNDRV_PCM_FORMAT_S32_LE:
bits = 32;
dma_params->pdc_xfer_size = 4;
break;
default:
printk(KERN_WARNING "at91-ssc: unsupported PCM format");
return -EINVAL;
}
/* /*
* The SSC only supports up to 16-bit samples in I2S format, due * The SSC only supports up to 16-bit samples in I2S format, due
* to the size of the Frame Mode Register FSLEN field. Also, I2S * to the size of the Frame Mode Register FSLEN field.
* implies signed data.
*/ */
bits = 16; if ((ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S
dma_params->pdc_xfer_size = 2; && bits > 16) {
printk(KERN_WARNING
"at91-ssc: sample size %d is too large for I2S\n", bits);
return -EINVAL;
}
/* /*
* Compute SSC register settings. * Compute SSC register settings.
*/ */
switch (ssc_p->daifmt) { switch (ssc_p->daifmt
case SND_SOC_DAIFMT_CBS_CFS: & (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_MASTER_MASK)) {
case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS:
/* /*
* SSC provides BCLK and LRC clocks. * I2S format, SSC provides BCLK and LRC clocks.
* *
* The SSC transmit and receive clocks are generated from the * The SSC transmit and receive clocks are generated from the
* MCK divider, and the BCLK signal is output on the SSC TK line. * MCK divider, and the BCLK signal is output on the SSC TK line.
...@@ -441,10 +469,9 @@ static int at91_i2s_hw_params(struct snd_pcm_substream *substream, ...@@ -441,10 +469,9 @@ static int at91_i2s_hw_params(struct snd_pcm_substream *substream,
| (((bits - 1) << 0) & AT91_SSC_DATALEN); | (((bits - 1) << 0) & AT91_SSC_DATALEN);
break; break;
case SND_SOC_DAIFMT_CBM_CFM: case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM:
/* /*
* CODEC supplies BCLK and LRC clocks. * I2S format, CODEC supplies BCLK and LRC clocks.
* *
* The SSC transmit clock is obtained from the BCLK signal on * The SSC transmit clock is obtained from the BCLK signal on
* on the TK line, and the SSC receive clock is generated from the * on the TK line, and the SSC receive clock is generated from the
...@@ -490,10 +517,51 @@ static int at91_i2s_hw_params(struct snd_pcm_substream *substream, ...@@ -490,10 +517,51 @@ static int at91_i2s_hw_params(struct snd_pcm_substream *substream,
| (((bits - 1) << 0) & AT91_SSC_DATALEN); | (((bits - 1) << 0) & AT91_SSC_DATALEN);
break; break;
case SND_SOC_DAIFMT_CBS_CFM: case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS:
case SND_SOC_DAIFMT_CBM_CFS: /*
* DSP/PCM Mode A format, SSC provides BCLK and LRC clocks.
*
* The SSC transmit and receive clocks are generated from the
* MCK divider, and the BCLK signal is output on the SSC TK line.
*/
rcmr = (( ssc_p->rcmr_period << 24) & AT91_SSC_PERIOD)
| (( 1 << 16) & AT91_SSC_STTDLY)
| (( AT91_SSC_START_RISING_RF ) & AT91_SSC_START)
| (( AT91_SSC_CK_RISING ) & AT91_SSC_CKI)
| (( AT91_SSC_CKO_NONE ) & AT91_SSC_CKO)
| (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS);
rfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
| (( AT91_SSC_FSOS_POSITIVE ) & AT91_SSC_FSOS)
| (( 0 << 16) & AT91_SSC_FSLEN)
| (((channels - 1) << 8) & AT91_SSC_DATNB)
| (( 1 << 7) & AT91_SSC_MSBF)
| (( 0 << 5) & AT91_SSC_LOOP)
| (((bits - 1) << 0) & AT91_SSC_DATALEN);
tcmr = (( ssc_p->tcmr_period << 24) & AT91_SSC_PERIOD)
| (( 1 << 16) & AT91_SSC_STTDLY)
| (( AT91_SSC_START_RISING_RF ) & AT91_SSC_START)
| (( AT91_SSC_CK_RISING ) & AT91_SSC_CKI)
| (( AT91_SSC_CKO_CONTINUOUS ) & AT91_SSC_CKO)
| (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS);
tfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
| (( 0 << 23) & AT91_SSC_FSDEN)
| (( AT91_SSC_FSOS_POSITIVE ) & AT91_SSC_FSOS)
| (( 0 << 16) & AT91_SSC_FSLEN)
| (((channels - 1) << 8) & AT91_SSC_DATNB)
| (( 1 << 7) & AT91_SSC_MSBF)
| (( 0 << 5) & AT91_SSC_DATDEF)
| (((bits - 1) << 0) & AT91_SSC_DATALEN);
break;
case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM:
default: default:
printk(KERN_WARNING "at91-i2s: unsupported DAI format 0x%x.\n", printk(KERN_WARNING "at91-ssc: unsupported DAI format 0x%x.\n",
ssc_p->daifmt); ssc_p->daifmt);
return -EINVAL; return -EINVAL;
break; break;
...@@ -518,9 +586,9 @@ static int at91_i2s_hw_params(struct snd_pcm_substream *substream, ...@@ -518,9 +586,9 @@ static int at91_i2s_hw_params(struct snd_pcm_substream *substream,
at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TNPR, 0); at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TNPR, 0);
at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TNCR, 0); at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TNCR, 0);
if ((ret = request_irq(ssc_p->ssc.pid, at91_i2s_interrupt, if ((ret = request_irq(ssc_p->ssc.pid, at91_ssc_interrupt,
0, ssc_p->name, ssc_p)) < 0) { 0, ssc_p->name, ssc_p)) < 0) {
printk(KERN_WARNING "at91-i2s: request_irq failure\n"); printk(KERN_WARNING "at91-ssc: request_irq failure\n");
DBG("Stopping pid %d clock\n", ssc_p->ssc.pid); DBG("Stopping pid %d clock\n", ssc_p->ssc.pid);
at91_sys_write(AT91_PMC_PCER, 1<<ssc_p->ssc.pid); at91_sys_write(AT91_PMC_PCER, 1<<ssc_p->ssc.pid);
...@@ -546,7 +614,7 @@ static int at91_i2s_hw_params(struct snd_pcm_substream *substream, ...@@ -546,7 +614,7 @@ static int at91_i2s_hw_params(struct snd_pcm_substream *substream,
} }
static int at91_i2s_prepare(struct snd_pcm_substream *substream) static int at91_ssc_prepare(struct snd_pcm_substream *substream)
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id]; struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
...@@ -566,7 +634,7 @@ static int at91_i2s_prepare(struct snd_pcm_substream *substream) ...@@ -566,7 +634,7 @@ static int at91_i2s_prepare(struct snd_pcm_substream *substream)
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int at91_i2s_suspend(struct platform_device *pdev, static int at91_ssc_suspend(struct platform_device *pdev,
struct snd_soc_cpu_dai *cpu_dai) struct snd_soc_cpu_dai *cpu_dai)
{ {
struct at91_ssc_info *ssc_p; struct at91_ssc_info *ssc_p;
...@@ -594,7 +662,7 @@ static int at91_i2s_suspend(struct platform_device *pdev, ...@@ -594,7 +662,7 @@ static int at91_i2s_suspend(struct platform_device *pdev,
return 0; return 0;
} }
static int at91_i2s_resume(struct platform_device *pdev, static int at91_ssc_resume(struct platform_device *pdev,
struct snd_soc_cpu_dai *cpu_dai) struct snd_soc_cpu_dai *cpu_dai)
{ {
struct at91_ssc_info *ssc_p; struct at91_ssc_info *ssc_p;
...@@ -620,102 +688,105 @@ static int at91_i2s_resume(struct platform_device *pdev, ...@@ -620,102 +688,105 @@ static int at91_i2s_resume(struct platform_device *pdev,
} }
#else #else
#define at91_i2s_suspend NULL #define at91_ssc_suspend NULL
#define at91_i2s_resume NULL #define at91_ssc_resume NULL
#endif #endif
#define AT91_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ #define AT91_SSC_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\ SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\ SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\
SNDRV_PCM_RATE_96000) SNDRV_PCM_RATE_96000)
struct snd_soc_cpu_dai at91_i2s_dai[NUM_SSC_DEVICES] = { #define AT91_SSC_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\
{ .name = "at91_ssc0/i2s", SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
struct snd_soc_cpu_dai at91_ssc_dai[NUM_SSC_DEVICES] = {
{ .name = "at91-ssc0",
.id = 0, .id = 0,
.type = SND_SOC_DAI_I2S, .type = SND_SOC_DAI_PCM,
.suspend = at91_i2s_suspend, .suspend = at91_ssc_suspend,
.resume = at91_i2s_resume, .resume = at91_ssc_resume,
.playback = { .playback = {
.channels_min = 1, .channels_min = 1,
.channels_max = 2, .channels_max = 2,
.rates = AT91_I2S_RATES, .rates = AT91_SSC_RATES,
.formats = SNDRV_PCM_FMTBIT_S16_LE,}, .formats = AT91_SSC_FORMATS,},
.capture = { .capture = {
.channels_min = 1, .channels_min = 1,
.channels_max = 2, .channels_max = 2,
.rates = AT91_I2S_RATES, .rates = AT91_SSC_RATES,
.formats = SNDRV_PCM_FMTBIT_S16_LE,}, .formats = AT91_SSC_FORMATS,},
.ops = { .ops = {
.startup = at91_i2s_startup, .startup = at91_ssc_startup,
.shutdown = at91_i2s_shutdown, .shutdown = at91_ssc_shutdown,
.prepare = at91_i2s_prepare, .prepare = at91_ssc_prepare,
.hw_params = at91_i2s_hw_params,}, .hw_params = at91_ssc_hw_params,},
.dai_ops = { .dai_ops = {
.set_sysclk = at91_i2s_set_dai_sysclk, .set_sysclk = at91_ssc_set_dai_sysclk,
.set_fmt = at91_i2s_set_dai_fmt, .set_fmt = at91_ssc_set_dai_fmt,
.set_clkdiv = at91_i2s_set_dai_clkdiv,}, .set_clkdiv = at91_ssc_set_dai_clkdiv,},
.private_data = &ssc_info[0].ssc, .private_data = &ssc_info[0].ssc,
}, },
#if NUM_SSC_DEVICES == 3 #if NUM_SSC_DEVICES == 3
{ .name = "at91_ssc1/i2s", { .name = "at91-ssc1",
.id = 1, .id = 1,
.type = SND_SOC_DAI_I2S, .type = SND_SOC_DAI_PCM,
.suspend = at91_i2s_suspend, .suspend = at91_ssc_suspend,
.resume = at91_i2s_resume, .resume = at91_ssc_resume,
.playback = { .playback = {
.channels_min = 1, .channels_min = 1,
.channels_max = 2, .channels_max = 2,
.rates = AT91_I2S_RATES, .rates = AT91_SSC_RATES,
.formats = SNDRV_PCM_FMTBIT_S16_LE,}, .formats = AT91_SSC_FORMATS,},
.capture = { .capture = {
.channels_min = 1, .channels_min = 1,
.channels_max = 2, .channels_max = 2,
.rates = AT91_I2S_RATES, .rates = AT91_SSC_RATES,
.formats = SNDRV_PCM_FMTBIT_S16_LE,}, .formats = AT91_SSC_FORMATS,},
.ops = { .ops = {
.startup = at91_i2s_startup, .startup = at91_ssc_startup,
.shutdown = at91_i2s_shutdown, .shutdown = at91_ssc_shutdown,
.prepare = at91_i2s_prepare, .prepare = at91_ssc_prepare,
.hw_params = at91_i2s_hw_params,}, .hw_params = at91_ssc_hw_params,},
.dai_ops = { .dai_ops = {
.set_sysclk = at91_i2s_set_dai_sysclk, .set_sysclk = at91_ssc_set_dai_sysclk,
.set_fmt = at91_i2s_set_dai_fmt, .set_fmt = at91_ssc_set_dai_fmt,
.set_clkdiv = at91_i2s_set_dai_clkdiv,}, .set_clkdiv = at91_ssc_set_dai_clkdiv,},
.private_data = &ssc_info[1].ssc, .private_data = &ssc_info[1].ssc,
}, },
{ .name = "at91_ssc2/i2s", { .name = "at91-ssc2",
.id = 2, .id = 2,
.type = SND_SOC_DAI_I2S, .type = SND_SOC_DAI_PCM,
.suspend = at91_i2s_suspend, .suspend = at91_ssc_suspend,
.resume = at91_i2s_resume, .resume = at91_ssc_resume,
.playback = { .playback = {
.channels_min = 1, .channels_min = 1,
.channels_max = 2, .channels_max = 2,
.rates = AT91_I2S_RATES, .rates = AT91_SSC_RATES,
.formats = SNDRV_PCM_FMTBIT_S16_LE,}, .formats = AT91_SSC_FORMATS,},
.capture = { .capture = {
.channels_min = 1, .channels_min = 1,
.channels_max = 2, .channels_max = 2,
.rates = AT91_I2S_RATES, .rates = AT91_SSC_RATES,
.formats = SNDRV_PCM_FMTBIT_S16_LE,}, .formats = AT91_SSC_FORMATS,},
.ops = { .ops = {
.startup = at91_i2s_startup, .startup = at91_ssc_startup,
.shutdown = at91_i2s_shutdown, .shutdown = at91_ssc_shutdown,
.prepare = at91_i2s_prepare, .prepare = at91_ssc_prepare,
.hw_params = at91_i2s_hw_params,}, .hw_params = at91_ssc_hw_params,},
.dai_ops = { .dai_ops = {
.set_sysclk = at91_i2s_set_dai_sysclk, .set_sysclk = at91_ssc_set_dai_sysclk,
.set_fmt = at91_i2s_set_dai_fmt, .set_fmt = at91_ssc_set_dai_fmt,
.set_clkdiv = at91_i2s_set_dai_clkdiv,}, .set_clkdiv = at91_ssc_set_dai_clkdiv,},
.private_data = &ssc_info[2].ssc, .private_data = &ssc_info[2].ssc,
}, },
#endif #endif
}; };
EXPORT_SYMBOL_GPL(at91_i2s_dai); EXPORT_SYMBOL_GPL(at91_ssc_dai);
/* Module information */ /* Module information */
MODULE_AUTHOR("Frank Mandarino, fmandarino@endrelia.com, www.endrelia.com"); MODULE_AUTHOR("Frank Mandarino, fmandarino@endrelia.com, www.endrelia.com");
MODULE_DESCRIPTION("AT91 I2S ASoC Interface"); MODULE_DESCRIPTION("AT91 SSC ASoC Interface");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
/* /*
* at91-i2s.h - ALSA I2S interface for the Atmel AT91 SoC * at91-ssc.h - ALSA SSC interface for the Atmel AT91 SoC
* *
* Author: Frank Mandarino <fmandarino@endrelia.com> * Author: Frank Mandarino <fmandarino@endrelia.com>
* Endrelia Technologies Inc. * Endrelia Technologies Inc.
...@@ -10,18 +10,18 @@ ...@@ -10,18 +10,18 @@
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ */
#ifndef _AT91_I2S_H #ifndef _AT91_SSC_H
#define _AT91_I2S_H #define _AT91_SSC_H
/* I2S system clock ids */ /* SSC system clock ids */
#define AT91_SYSCLK_MCK 0 /* SSC uses AT91 MCK as system clock */ #define AT91_SYSCLK_MCK 0 /* SSC uses AT91 MCK as system clock */
/* I2S divider ids */ /* SSC divider ids */
#define AT91SSC_CMR_DIV 0 /* MCK divider for BCLK */ #define AT91SSC_CMR_DIV 0 /* MCK divider for BCLK */
#define AT91SSC_TCMR_PERIOD 1 /* BCLK divider for transmit FS */ #define AT91SSC_TCMR_PERIOD 1 /* BCLK divider for transmit FS */
#define AT91SSC_RCMR_PERIOD 2 /* BCLK divider for receive FS */ #define AT91SSC_RCMR_PERIOD 2 /* BCLK divider for receive FS */
extern struct snd_soc_cpu_dai at91_i2s_dai[]; extern struct snd_soc_cpu_dai at91_ssc_dai[];
#endif /* _AT91_I2S_H */ #endif /* _AT91_SSC_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment