31 #include <linux/module.h>
33 #include <linux/device.h>
45 #include <mach/hardware.h>
51 #if defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9G20)
52 #define NUM_SSC_DEVICES 1
54 #define NUM_SSC_DEVICES 3
79 .ssc_disable =
SSC_BIT(CR_TXDIS),
81 .ssc_endbuf =
SSC_BIT(SR_TXBUFE),
88 .ssc_disable =
SSC_BIT(CR_RXDIS),
90 .ssc_endbuf =
SSC_BIT(SR_RXBUFF),
101 .name =
"SSC0 PCM out",
103 .mask = &ssc_tx_mask,
106 .name =
"SSC0 PCM in",
108 .mask = &ssc_rx_mask,
110 #if NUM_SSC_DEVICES == 3
112 .name =
"SSC1 PCM out",
114 .mask = &ssc_tx_mask,
117 .name =
"SSC1 PCM in",
119 .mask = &ssc_rx_mask,
122 .name =
"SSC2 PCM out",
124 .mask = &ssc_tx_mask,
127 .name =
"SSC2 PCM in",
129 .mask = &ssc_rx_mask,
142 #if NUM_SSC_DEVICES == 3
168 u32 ssc_substream_mask;
183 if ((dma_params !=
NULL) &&
185 ssc_substream_mask = (dma_params->
mask->ssc_endx |
186 dma_params->
mask->ssc_endbuf);
187 if (ssc_sr & ssc_substream_mask) {
211 pr_debug(
"atmel_ssc_startup: SSC_SR=0x%u\n",
219 spin_lock_irq(&ssc_p->
lock);
221 spin_unlock_irq(&ssc_p->
lock);
225 spin_unlock_irq(&ssc_p->
lock);
248 if (dma_params !=
NULL) {
250 pr_debug(
"atmel_ssc_shutdown: %s disabled SSC_SR=0x%08x\n",
251 (dir ?
"receive" :
"transmit"),
261 spin_lock_irq(&ssc_p->
lock);
266 pr_debug(
"atmel_ssc_dau: Stopping clock\n");
278 spin_unlock_irq(&ssc_p->
lock);
285 static int atmel_ssc_set_dai_fmt(
struct snd_soc_dai *cpu_dai,
297 static int atmel_ssc_set_dai_clkdiv(
struct snd_soc_dai *cpu_dai,
343 u32 tfmr, rfmr, tcmr, rcmr;
357 dma_params = &ssc_dma_params[
id][dir];
358 dma_params->
ssc = ssc_p->
ssc;
369 snd_soc_dai_set_dma_data(rtd->
cpu_dai, substream, dma_params);
405 "atmel_ssc_dai: sample size %d "
406 "is too large for I2S\n", bits);
433 |
SSC_BF(RFMR_FSLEN, (bits - 1))
434 |
SSC_BF(RFMR_DATNB, (channels - 1))
437 |
SSC_BF(RFMR_DATLEN, (bits - 1));
449 |
SSC_BF(TFMR_FSLEN, (bits - 1))
450 |
SSC_BF(TFMR_DATNB, (channels - 1))
453 |
SSC_BF(TFMR_DATLEN, (bits - 1));
469 start_event = ((channels == 1)
473 rcmr =
SSC_BF(RCMR_PERIOD, 0)
475 |
SSC_BF(RCMR_START, start_event)
486 |
SSC_BF(RFMR_DATLEN, (bits - 1));
488 tcmr =
SSC_BF(TCMR_PERIOD, 0)
490 |
SSC_BF(TCMR_START, start_event)
502 |
SSC_BF(TFMR_DATLEN, (bits - 1));
523 |
SSC_BF(RFMR_DATNB, (channels - 1))
526 |
SSC_BF(RFMR_DATLEN, (bits - 1));
539 |
SSC_BF(TFMR_DATNB, (channels - 1))
542 |
SSC_BF(TFMR_DATLEN, (bits - 1));
552 "RCMR=%08x RFMR=%08x TCMR=%08x TFMR=%08x\n",
553 rcmr, rfmr, tcmr, tfmr);
558 pr_debug(
"atmel_ssc_dai: Starting clock\n");
578 "atmel_ssc_dai: request_irq failure\n");
579 pr_debug(
"Atmel_ssc_dai: Stoping clock\n");
598 pr_debug(
"atmel_ssc_dai,hw_params: SSC initialized\n");
619 pr_debug(
"%s enabled SSC_SR=0x%08x\n",
620 dir ?
"receive" :
"transmit",
634 ssc_p = &ssc_info[cpu_dai->
id];
663 ssc_p = &ssc_info[cpu_dai->
id];
686 # define atmel_ssc_suspend NULL
687 # define atmel_ssc_resume NULL
690 static int atmel_ssc_probe(
struct snd_soc_dai *dai)
695 snd_soc_dai_set_drvdata(dai, ssc_p);
701 if (IS_ERR(ssc_p->
ssc)) {
703 ret = PTR_ERR(ssc_p->
ssc);
709 static int atmel_ssc_remove(
struct snd_soc_dai *dai)
717 #define ATMEL_SSC_RATES (SNDRV_PCM_RATE_8000_96000)
719 #define ATMEL_SSC_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\
720 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
723 .startup = atmel_ssc_startup,
724 .shutdown = atmel_ssc_shutdown,
725 .prepare = atmel_ssc_prepare,
726 .hw_params = atmel_ssc_hw_params,
727 .set_fmt = atmel_ssc_set_dai_fmt,
728 .set_clkdiv = atmel_ssc_set_dai_clkdiv,
733 .name =
"atmel-ssc-dai.0",
734 .probe = atmel_ssc_probe,
735 .remove = atmel_ssc_remove,
748 .ops = &atmel_ssc_dai_ops,
750 #if NUM_SSC_DEVICES == 3
752 .name =
"atmel-ssc-dai.1",
753 .probe = atmel_ssc_probe,
754 .remove = atmel_ssc_remove,
767 .ops = &atmel_ssc_dai_ops,
770 .name =
"atmel-ssc-dai.2",
771 .probe = atmel_ssc_probe,
772 .remove = atmel_ssc_remove,
785 .ops = &atmel_ssc_dai_ops,
805 .name =
"atmel-ssc-dai",
809 .probe = asoc_ssc_probe,
823 if (ssc_id < 0 || ssc_id >=
ARRAY_SIZE(atmel_ssc_dai))
847 pr_warn(
"Unable to parent ASoC SSC DAI on SSC: %ld\n",
850 ssc_pdev->
dev.parent = &(ssc->
pdev->dev);