15 #include <linux/module.h>
18 #include <linux/device.h>
20 #include <linux/slab.h>
35 #define read_ssi(addr) in_be32(addr)
36 #define write_ssi(val, addr) out_be32(addr, val)
37 #define write_ssi_mask(addr, clear, set) clrsetbits_be32(addr, clear, set)
39 #define read_ssi(addr) readl(addr)
40 #define write_ssi(val, addr) writel(val, addr)
48 val = (val & ~clear) |
set;
61 #define FSLSSI_I2S_RATES (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_192000 | \
62 SNDRV_PCM_RATE_CONTINUOUS)
79 #define FSLSSI_I2S_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE | \
80 SNDRV_PCM_FMTBIT_S18_3BE | SNDRV_PCM_FMTBIT_S20_3BE | \
81 SNDRV_PCM_FMTBIT_S24_3BE | SNDRV_PCM_FMTBIT_S24_BE)
83 #define FSLSSI_I2S_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | \
84 SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S20_3LE | \
85 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE)
89 #define SIER_FLAGS (CCSR_SSI_SIER_TFRC_EN | CCSR_SSI_SIER_TDMAE | \
90 CCSR_SSI_SIER_TIE | CCSR_SSI_SIER_TUE0_EN | \
91 CCSR_SSI_SIER_TUE1_EN | CCSR_SSI_SIER_RFRC_EN | \
92 CCSR_SSI_SIER_RDMAE | CCSR_SSI_SIER_RIE | \
93 CCSR_SSI_SIER_ROE0_EN | CCSR_SSI_SIER_ROE1_EN)
182 ssi_private->
stats.rfrc++;
188 ssi_private->
stats.tfrc++;
194 ssi_private->
stats.cmdau++;
199 ssi_private->
stats.cmddu++;
204 ssi_private->
stats.rxt++;
209 ssi_private->
stats.rdr1++;
214 ssi_private->
stats.rdr0++;
219 ssi_private->
stats.tde1++;
224 ssi_private->
stats.tde0++;
229 ssi_private->
stats.roe1++;
235 ssi_private->
stats.roe0++;
241 ssi_private->
stats.tue1++;
247 ssi_private->
stats.tue0++;
253 ssi_private->
stats.tfs++;
258 ssi_private->
stats.rfs++;
263 ssi_private->
stats.tls++;
268 ssi_private->
stats.rls++;
273 ssi_private->
stats.rff1++;
278 ssi_private->
stats.rff0++;
283 ssi_private->
stats.tfe1++;
288 ssi_private->
stats.tfe0++;
294 write_ssi(sisr2, &ssi->
sisr);
312 snd_soc_dai_get_drvdata(rtd->
cpu_dai);
313 int synchronous = ssi_private->
cpu_dai_drv.symmetric_rates;
337 write_ssi_mask(&ssi->
scr,
409 "set sample size in %s stream first\n",
412 ?
"capture" :
"playback");
426 snd_soc_dai_set_dma_data(dai, substream,
450 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
461 if (enabled && ssi_private->
cpu_dai_drv.symmetric_rates)
504 write_ssi_mask(&ssi->
scr, 0,
507 write_ssi_mask(&ssi->
scr, 0,
553 .startup = fsl_ssi_startup,
554 .hw_params = fsl_ssi_hw_params,
555 .shutdown = fsl_ssi_shutdown,
556 .trigger = fsl_ssi_trigger,
574 .ops = &fsl_ssi_dai_ops,
581 #define SIER_SHOW(flag, name) \
583 if (SIER_FLAGS & CCSR_SSI_SIER_##flag) \
584 length += sprintf(buf + length, #name "=%u\n", \
585 ssi_private->stats.name); \
630 static void make_lowercase(
char *
s)
636 if ((c >=
'A') && (c <=
'Z'))
637 *p = c + (
'a' -
'A');
648 const char *
p, *sprop;
662 if (!sprop ||
strcmp(sprop,
"i2s-slave")) {
663 dev_notice(&pdev->
dev,
"mode %s is unsupported\n", sprop);
672 dev_err(&pdev->
dev,
"could not allocate DAI object\n");
680 sizeof(fsl_ssi_dai_template));
686 dev_err(&pdev->
dev,
"could not determine device resources\n");
690 if (!ssi_private->
ssi) {
691 dev_err(&pdev->
dev,
"could not map device resources\n");
708 dev_err(&pdev->
dev,
"could not claim irq %u\n", ssi_private->
irq);
729 if (IS_ERR(ssi_private->
clk)) {
730 ret = PTR_ERR(ssi_private->
clk);
731 dev_err(&pdev->
dev,
"could not get clock: %d\n", ret);
734 clk_prepare_enable(ssi_private->
clk);
753 "fsl,ssi-dma-events", dma_events, 2);
755 dev_err(&pdev->
dev,
"could not get dma events\n");
771 dev_attr->
attr.name =
"statistics";
773 dev_attr->
show = fsl_sysfs_ssi_show;
777 dev_err(&pdev->
dev,
"could not create sysfs %s file\n",
787 dev_err(&pdev->
dev,
"failed to register DAI: %d\n", ret);
793 platform_device_register_simple(
"imx-pcm-audio",
821 snprintf(name,
sizeof(name),
"snd-soc-%s", sprop);
822 make_lowercase(name);
825 platform_device_register_data(&pdev->
dev, name, 0,
NULL, 0);
826 if (IS_ERR(ssi_private->
pdev)) {
827 ret = PTR_ERR(ssi_private->
pdev);
828 dev_err(&pdev->
dev,
"failed to register platform: %d\n", ret);
846 clk_disable_unprepare(ssi_private->
clk);
873 clk_disable_unprepare(ssi_private->
clk);
889 { .compatible =
"fsl,mpc8610-ssi", },
890 { .compatible =
"fsl,imx21-ssi", },
897 .name =
"fsl-ssi-dai",
899 .of_match_table = fsl_ssi_ids,
901 .probe = fsl_ssi_probe,
902 .remove = fsl_ssi_remove,