1
2
3
4
5
6
7
8
9
10
11
12#include <linux/init.h>
13#include <linux/module.h>
14#include <linux/interrupt.h>
15#include <linux/device.h>
16#include <linux/delay.h>
17
18#include <sound/core.h>
19#include <sound/pcm.h>
20#include <sound/pcm_params.h>
21#include <sound/initval.h>
22#include <sound/soc.h>
23
24#include <asm/immap_86xx.h>
25
26#include "fsl_ssi.h"
27
28
29
30
31
32
33
34
35
36#define FSLSSI_I2S_RATES (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_192000 | \
37 SNDRV_PCM_RATE_CONTINUOUS)
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53#ifdef __BIG_ENDIAN
54#define FSLSSI_I2S_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE | \
55 SNDRV_PCM_FMTBIT_S18_3BE | SNDRV_PCM_FMTBIT_S20_3BE | \
56 SNDRV_PCM_FMTBIT_S24_3BE | SNDRV_PCM_FMTBIT_S24_BE)
57#else
58#define FSLSSI_I2S_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | \
59 SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S20_3LE | \
60 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE)
61#endif
62
63
64#define SIER_FLAGS (CCSR_SSI_SIER_TFRC_EN | CCSR_SSI_SIER_TDMAE | \
65 CCSR_SSI_SIER_TIE | CCSR_SSI_SIER_TUE0_EN | \
66 CCSR_SSI_SIER_TUE1_EN | CCSR_SSI_SIER_RFRC_EN | \
67 CCSR_SSI_SIER_RDMAE | CCSR_SSI_SIER_RIE | \
68 CCSR_SSI_SIER_ROE0_EN | CCSR_SSI_SIER_ROE1_EN)
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87struct fsl_ssi_private {
88 char name[8];
89 struct ccsr_ssi __iomem *ssi;
90 dma_addr_t ssi_phys;
91 unsigned int irq;
92 struct snd_pcm_substream *first_stream;
93 struct snd_pcm_substream *second_stream;
94 struct device *dev;
95 unsigned int playback;
96 unsigned int capture;
97 int asynchronous;
98 struct snd_soc_dai cpu_dai;
99 struct device_attribute dev_attr;
100
101 struct {
102 unsigned int rfrc;
103 unsigned int tfrc;
104 unsigned int cmdau;
105 unsigned int cmddu;
106 unsigned int rxt;
107 unsigned int rdr1;
108 unsigned int rdr0;
109 unsigned int tde1;
110 unsigned int tde0;
111 unsigned int roe1;
112 unsigned int roe0;
113 unsigned int tue1;
114 unsigned int tue0;
115 unsigned int tfs;
116 unsigned int rfs;
117 unsigned int tls;
118 unsigned int rls;
119 unsigned int rff1;
120 unsigned int rff0;
121 unsigned int tfe1;
122 unsigned int tfe0;
123 } stats;
124};
125
126
127
128
129
130
131
132
133
134
135
136
137
138static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
139{
140 struct fsl_ssi_private *ssi_private = dev_id;
141 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
142 irqreturn_t ret = IRQ_NONE;
143 __be32 sisr;
144 __be32 sisr2 = 0;
145
146
147
148
149
150 sisr = in_be32(&ssi->sisr) & SIER_FLAGS;
151
152 if (sisr & CCSR_SSI_SISR_RFRC) {
153 ssi_private->stats.rfrc++;
154 sisr2 |= CCSR_SSI_SISR_RFRC;
155 ret = IRQ_HANDLED;
156 }
157
158 if (sisr & CCSR_SSI_SISR_TFRC) {
159 ssi_private->stats.tfrc++;
160 sisr2 |= CCSR_SSI_SISR_TFRC;
161 ret = IRQ_HANDLED;
162 }
163
164 if (sisr & CCSR_SSI_SISR_CMDAU) {
165 ssi_private->stats.cmdau++;
166 ret = IRQ_HANDLED;
167 }
168
169 if (sisr & CCSR_SSI_SISR_CMDDU) {
170 ssi_private->stats.cmddu++;
171 ret = IRQ_HANDLED;
172 }
173
174 if (sisr & CCSR_SSI_SISR_RXT) {
175 ssi_private->stats.rxt++;
176 ret = IRQ_HANDLED;
177 }
178
179 if (sisr & CCSR_SSI_SISR_RDR1) {
180 ssi_private->stats.rdr1++;
181 ret = IRQ_HANDLED;
182 }
183
184 if (sisr & CCSR_SSI_SISR_RDR0) {
185 ssi_private->stats.rdr0++;
186 ret = IRQ_HANDLED;
187 }
188
189 if (sisr & CCSR_SSI_SISR_TDE1) {
190 ssi_private->stats.tde1++;
191 ret = IRQ_HANDLED;
192 }
193
194 if (sisr & CCSR_SSI_SISR_TDE0) {
195 ssi_private->stats.tde0++;
196 ret = IRQ_HANDLED;
197 }
198
199 if (sisr & CCSR_SSI_SISR_ROE1) {
200 ssi_private->stats.roe1++;
201 sisr2 |= CCSR_SSI_SISR_ROE1;
202 ret = IRQ_HANDLED;
203 }
204
205 if (sisr & CCSR_SSI_SISR_ROE0) {
206 ssi_private->stats.roe0++;
207 sisr2 |= CCSR_SSI_SISR_ROE0;
208 ret = IRQ_HANDLED;
209 }
210
211 if (sisr & CCSR_SSI_SISR_TUE1) {
212 ssi_private->stats.tue1++;
213 sisr2 |= CCSR_SSI_SISR_TUE1;
214 ret = IRQ_HANDLED;
215 }
216
217 if (sisr & CCSR_SSI_SISR_TUE0) {
218 ssi_private->stats.tue0++;
219 sisr2 |= CCSR_SSI_SISR_TUE0;
220 ret = IRQ_HANDLED;
221 }
222
223 if (sisr & CCSR_SSI_SISR_TFS) {
224 ssi_private->stats.tfs++;
225 ret = IRQ_HANDLED;
226 }
227
228 if (sisr & CCSR_SSI_SISR_RFS) {
229 ssi_private->stats.rfs++;
230 ret = IRQ_HANDLED;
231 }
232
233 if (sisr & CCSR_SSI_SISR_TLS) {
234 ssi_private->stats.tls++;
235 ret = IRQ_HANDLED;
236 }
237
238 if (sisr & CCSR_SSI_SISR_RLS) {
239 ssi_private->stats.rls++;
240 ret = IRQ_HANDLED;
241 }
242
243 if (sisr & CCSR_SSI_SISR_RFF1) {
244 ssi_private->stats.rff1++;
245 ret = IRQ_HANDLED;
246 }
247
248 if (sisr & CCSR_SSI_SISR_RFF0) {
249 ssi_private->stats.rff0++;
250 ret = IRQ_HANDLED;
251 }
252
253 if (sisr & CCSR_SSI_SISR_TFE1) {
254 ssi_private->stats.tfe1++;
255 ret = IRQ_HANDLED;
256 }
257
258 if (sisr & CCSR_SSI_SISR_TFE0) {
259 ssi_private->stats.tfe0++;
260 ret = IRQ_HANDLED;
261 }
262
263
264 if (sisr2)
265 out_be32(&ssi->sisr, sisr2);
266
267 return ret;
268}
269
270
271
272
273
274
275
276
277
278static int fsl_ssi_startup(struct snd_pcm_substream *substream,
279 struct snd_soc_dai *dai)
280{
281 struct snd_soc_pcm_runtime *rtd = substream->private_data;
282 struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data;
283
284
285
286
287
288 if (!ssi_private->playback && !ssi_private->capture) {
289 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
290 int ret;
291
292 ret = request_irq(ssi_private->irq, fsl_ssi_isr, 0,
293 ssi_private->name, ssi_private);
294 if (ret < 0) {
295 dev_err(substream->pcm->card->dev,
296 "could not claim irq %u\n", ssi_private->irq);
297 return ret;
298 }
299
300
301
302
303
304
305 clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN);
306
307
308
309
310
311
312
313 clrsetbits_be32(&ssi->scr,
314 CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_SYN,
315 CCSR_SSI_SCR_TFR_CLK_DIS | CCSR_SSI_SCR_I2S_MODE_SLAVE
316 | (ssi_private->asynchronous ? 0 : CCSR_SSI_SCR_SYN));
317
318 out_be32(&ssi->stcr,
319 CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 |
320 CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TEFS |
321 CCSR_SSI_STCR_TSCKP);
322
323 out_be32(&ssi->srcr,
324 CCSR_SSI_SRCR_RXBIT0 | CCSR_SSI_SRCR_RFEN0 |
325 CCSR_SSI_SRCR_RFSI | CCSR_SSI_SRCR_REFS |
326 CCSR_SSI_SRCR_RSCKP);
327
328
329
330
331
332
333
334 out_be32(&ssi->sier, SIER_FLAGS);
335
336
337
338
339
340
341 out_be32(&ssi->sfcsr,
342 CCSR_SSI_SFCSR_TFWM0(6) | CCSR_SSI_SFCSR_RFWM0(2));
343
344
345
346
347
348
349
350
351
352
353 }
354
355 if (!ssi_private->first_stream)
356 ssi_private->first_stream = substream;
357 else {
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375 struct snd_pcm_runtime *first_runtime =
376 ssi_private->first_stream->runtime;
377
378 if (!first_runtime->sample_bits) {
379 dev_err(substream->pcm->card->dev,
380 "set sample size in %s stream first\n",
381 substream->stream == SNDRV_PCM_STREAM_PLAYBACK
382 ? "capture" : "playback");
383 return -EAGAIN;
384 }
385
386
387
388
389
390 if (!ssi_private->asynchronous)
391 snd_pcm_hw_constraint_minmax(substream->runtime,
392 SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
393 first_runtime->sample_bits,
394 first_runtime->sample_bits);
395
396 ssi_private->second_stream = substream;
397 }
398
399 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
400 ssi_private->playback++;
401
402 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
403 ssi_private->capture++;
404
405 return 0;
406}
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
422 struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *cpu_dai)
423{
424 struct fsl_ssi_private *ssi_private = cpu_dai->private_data;
425
426 if (substream == ssi_private->first_stream) {
427 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
428 unsigned int sample_size =
429 snd_pcm_format_width(params_format(hw_params));
430 u32 wl = CCSR_SSI_SxCCR_WL(sample_size);
431
432
433
434
435 if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ||
436 !ssi_private->asynchronous)
437 clrsetbits_be32(&ssi->stccr,
438 CCSR_SSI_SxCCR_WL_MASK, wl);
439 else
440 clrsetbits_be32(&ssi->srccr,
441 CCSR_SSI_SxCCR_WL_MASK, wl);
442 }
443
444 return 0;
445}
446
447
448
449
450
451
452
453
454
455
456static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
457 struct snd_soc_dai *dai)
458{
459 struct snd_soc_pcm_runtime *rtd = substream->private_data;
460 struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data;
461 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
462
463 switch (cmd) {
464 case SNDRV_PCM_TRIGGER_START:
465 clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN);
466 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
467 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
468 setbits32(&ssi->scr,
469 CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_TE);
470 else
471 setbits32(&ssi->scr,
472 CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_RE);
473 break;
474
475 case SNDRV_PCM_TRIGGER_STOP:
476 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
477 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
478 clrbits32(&ssi->scr, CCSR_SSI_SCR_TE);
479 else
480 clrbits32(&ssi->scr, CCSR_SSI_SCR_RE);
481 break;
482
483 default:
484 return -EINVAL;
485 }
486
487 return 0;
488}
489
490
491
492
493
494
495static void fsl_ssi_shutdown(struct snd_pcm_substream *substream,
496 struct snd_soc_dai *dai)
497{
498 struct snd_soc_pcm_runtime *rtd = substream->private_data;
499 struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data;
500
501 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
502 ssi_private->playback--;
503
504 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
505 ssi_private->capture--;
506
507 if (ssi_private->first_stream == substream)
508 ssi_private->first_stream = ssi_private->second_stream;
509
510 ssi_private->second_stream = NULL;
511
512
513
514
515
516 if (!ssi_private->playback && !ssi_private->capture) {
517 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
518
519 clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN);
520
521 free_irq(ssi_private->irq, ssi_private);
522 }
523}
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539static int fsl_ssi_set_sysclk(struct snd_soc_dai *cpu_dai,
540 int clk_id, unsigned int freq, int dir)
541{
542
543 return (dir == SND_SOC_CLOCK_IN) ? 0 : -EINVAL;
544}
545
546
547
548
549
550
551
552
553
554
555
556
557static int fsl_ssi_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int format)
558{
559 return (format == SND_SOC_DAIFMT_I2S) ? 0 : -EINVAL;
560}
561
562
563
564
565static struct snd_soc_dai_ops fsl_ssi_dai_ops = {
566 .startup = fsl_ssi_startup,
567 .hw_params = fsl_ssi_hw_params,
568 .shutdown = fsl_ssi_shutdown,
569 .trigger = fsl_ssi_trigger,
570 .set_sysclk = fsl_ssi_set_sysclk,
571 .set_fmt = fsl_ssi_set_fmt,
572};
573
574static struct snd_soc_dai fsl_ssi_dai_template = {
575 .playback = {
576
577 .channels_min = 2,
578 .channels_max = 2,
579 .rates = FSLSSI_I2S_RATES,
580 .formats = FSLSSI_I2S_FORMATS,
581 },
582 .capture = {
583 .channels_min = 2,
584 .channels_max = 2,
585 .rates = FSLSSI_I2S_RATES,
586 .formats = FSLSSI_I2S_FORMATS,
587 },
588 .ops = &fsl_ssi_dai_ops,
589};
590
591
592
593
594
595#define SIER_SHOW(flag, name) \
596 do { \
597 if (SIER_FLAGS & CCSR_SSI_SIER_##flag) \
598 length += sprintf(buf + length, #name "=%u\n", \
599 ssi_private->stats.name); \
600 } while (0)
601
602
603
604
605
606
607
608
609static ssize_t fsl_sysfs_ssi_show(struct device *dev,
610 struct device_attribute *attr, char *buf)
611{
612 struct fsl_ssi_private *ssi_private =
613 container_of(attr, struct fsl_ssi_private, dev_attr);
614 ssize_t length = 0;
615
616 SIER_SHOW(RFRC_EN, rfrc);
617 SIER_SHOW(TFRC_EN, tfrc);
618 SIER_SHOW(CMDAU_EN, cmdau);
619 SIER_SHOW(CMDDU_EN, cmddu);
620 SIER_SHOW(RXT_EN, rxt);
621 SIER_SHOW(RDR1_EN, rdr1);
622 SIER_SHOW(RDR0_EN, rdr0);
623 SIER_SHOW(TDE1_EN, tde1);
624 SIER_SHOW(TDE0_EN, tde0);
625 SIER_SHOW(ROE1_EN, roe1);
626 SIER_SHOW(ROE0_EN, roe0);
627 SIER_SHOW(TUE1_EN, tue1);
628 SIER_SHOW(TUE0_EN, tue0);
629 SIER_SHOW(TFS_EN, tfs);
630 SIER_SHOW(RFS_EN, rfs);
631 SIER_SHOW(TLS_EN, tls);
632 SIER_SHOW(RLS_EN, rls);
633 SIER_SHOW(RFF1_EN, rff1);
634 SIER_SHOW(RFF0_EN, rff0);
635 SIER_SHOW(TFE1_EN, tfe1);
636 SIER_SHOW(TFE0_EN, tfe0);
637
638 return length;
639}
640
641
642
643
644
645
646
647
648struct snd_soc_dai *fsl_ssi_create_dai(struct fsl_ssi_info *ssi_info)
649{
650 struct snd_soc_dai *fsl_ssi_dai;
651 struct fsl_ssi_private *ssi_private;
652 int ret = 0;
653 struct device_attribute *dev_attr;
654
655 ssi_private = kzalloc(sizeof(struct fsl_ssi_private), GFP_KERNEL);
656 if (!ssi_private) {
657 dev_err(ssi_info->dev, "could not allocate DAI object\n");
658 return NULL;
659 }
660 memcpy(&ssi_private->cpu_dai, &fsl_ssi_dai_template,
661 sizeof(struct snd_soc_dai));
662
663 fsl_ssi_dai = &ssi_private->cpu_dai;
664 dev_attr = &ssi_private->dev_attr;
665
666 sprintf(ssi_private->name, "ssi%u", (u8) ssi_info->id);
667 ssi_private->ssi = ssi_info->ssi;
668 ssi_private->ssi_phys = ssi_info->ssi_phys;
669 ssi_private->irq = ssi_info->irq;
670 ssi_private->dev = ssi_info->dev;
671 ssi_private->asynchronous = ssi_info->asynchronous;
672
673 dev_set_drvdata(ssi_private->dev, fsl_ssi_dai);
674
675
676 dev_attr->attr.name = "ssi-stats";
677 dev_attr->attr.mode = S_IRUGO;
678 dev_attr->show = fsl_sysfs_ssi_show;
679
680 ret = device_create_file(ssi_private->dev, dev_attr);
681 if (ret) {
682 dev_err(ssi_info->dev, "could not create sysfs %s file\n",
683 ssi_private->dev_attr.attr.name);
684 kfree(fsl_ssi_dai);
685 return NULL;
686 }
687
688 fsl_ssi_dai->private_data = ssi_private;
689 fsl_ssi_dai->name = ssi_private->name;
690 fsl_ssi_dai->id = ssi_info->id;
691 fsl_ssi_dai->dev = ssi_info->dev;
692 fsl_ssi_dai->symmetric_rates = 1;
693
694 ret = snd_soc_register_dai(fsl_ssi_dai);
695 if (ret != 0) {
696 dev_err(ssi_info->dev, "failed to register DAI: %d\n", ret);
697 kfree(fsl_ssi_dai);
698 return NULL;
699 }
700
701 return fsl_ssi_dai;
702}
703EXPORT_SYMBOL_GPL(fsl_ssi_create_dai);
704
705
706
707
708
709
710void fsl_ssi_destroy_dai(struct snd_soc_dai *fsl_ssi_dai)
711{
712 struct fsl_ssi_private *ssi_private =
713 container_of(fsl_ssi_dai, struct fsl_ssi_private, cpu_dai);
714
715 device_remove_file(ssi_private->dev, &ssi_private->dev_attr);
716
717 snd_soc_unregister_dai(&ssi_private->cpu_dai);
718
719 kfree(ssi_private);
720}
721EXPORT_SYMBOL_GPL(fsl_ssi_destroy_dai);
722
723static int __init fsl_ssi_init(void)
724{
725 printk(KERN_INFO "Freescale Synchronous Serial Interface (SSI) ASoC Driver\n");
726
727 return 0;
728}
729module_init(fsl_ssi_init);
730
731MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
732MODULE_DESCRIPTION("Freescale Synchronous Serial Interface (SSI) ASoC Driver");
733MODULE_LICENSE("GPL");
734