1
2
3
4
5
6
7
8
9
10
11
12
13#include <linux/init.h>
14#include <linux/io.h>
15#include <linux/module.h>
16#include <linux/interrupt.h>
17#include <linux/clk.h>
18#include <linux/device.h>
19#include <linux/delay.h>
20#include <linux/slab.h>
21#include <linux/of_address.h>
22#include <linux/of_irq.h>
23#include <linux/of_platform.h>
24
25#include <sound/core.h>
26#include <sound/pcm.h>
27#include <sound/pcm_params.h>
28#include <sound/initval.h>
29#include <sound/soc.h>
30#include <sound/dmaengine_pcm.h>
31
32#include "fsl_ssi.h"
33#include "imx-pcm.h"
34
35#ifdef PPC
36#define read_ssi(addr) in_be32(addr)
37#define write_ssi(val, addr) out_be32(addr, val)
38#define write_ssi_mask(addr, clear, set) clrsetbits_be32(addr, clear, set)
39#elif defined ARM
40#define read_ssi(addr) readl(addr)
41#define write_ssi(val, addr) writel(val, addr)
42
43
44
45
46static inline void write_ssi_mask(u32 __iomem *addr, u32 clear, u32 set)
47{
48 u32 val = readl(addr);
49 val = (val & ~clear) | set;
50 writel(val, addr);
51}
52#endif
53
54
55
56
57
58
59
60
61
62#define FSLSSI_I2S_RATES (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_192000 | \
63 SNDRV_PCM_RATE_CONTINUOUS)
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79#ifdef __BIG_ENDIAN
80#define FSLSSI_I2S_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE | \
81 SNDRV_PCM_FMTBIT_S18_3BE | SNDRV_PCM_FMTBIT_S20_3BE | \
82 SNDRV_PCM_FMTBIT_S24_3BE | SNDRV_PCM_FMTBIT_S24_BE)
83#else
84#define FSLSSI_I2S_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | \
85 SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S20_3LE | \
86 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE)
87#endif
88
89
90#define SIER_FLAGS (CCSR_SSI_SIER_TFRC_EN | CCSR_SSI_SIER_TDMAE | \
91 CCSR_SSI_SIER_TIE | CCSR_SSI_SIER_TUE0_EN | \
92 CCSR_SSI_SIER_TUE1_EN | CCSR_SSI_SIER_RFRC_EN | \
93 CCSR_SSI_SIER_RDMAE | CCSR_SSI_SIER_RIE | \
94 CCSR_SSI_SIER_ROE0_EN | CCSR_SSI_SIER_ROE1_EN)
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111struct fsl_ssi_private {
112 struct ccsr_ssi __iomem *ssi;
113 dma_addr_t ssi_phys;
114 unsigned int irq;
115 struct snd_pcm_substream *first_stream;
116 struct snd_pcm_substream *second_stream;
117 unsigned int fifo_depth;
118 struct snd_soc_dai_driver cpu_dai_drv;
119 struct device_attribute dev_attr;
120 struct platform_device *pdev;
121
122 bool new_binding;
123 bool ssi_on_imx;
124 struct clk *clk;
125 struct platform_device *imx_pcm_pdev;
126 struct snd_dmaengine_dai_dma_data dma_params_tx;
127 struct snd_dmaengine_dai_dma_data dma_params_rx;
128 struct imx_dma_data filter_data_tx;
129 struct imx_dma_data filter_data_rx;
130
131 struct {
132 unsigned int rfrc;
133 unsigned int tfrc;
134 unsigned int cmdau;
135 unsigned int cmddu;
136 unsigned int rxt;
137 unsigned int rdr1;
138 unsigned int rdr0;
139 unsigned int tde1;
140 unsigned int tde0;
141 unsigned int roe1;
142 unsigned int roe0;
143 unsigned int tue1;
144 unsigned int tue0;
145 unsigned int tfs;
146 unsigned int rfs;
147 unsigned int tls;
148 unsigned int rls;
149 unsigned int rff1;
150 unsigned int rff0;
151 unsigned int tfe1;
152 unsigned int tfe0;
153 } stats;
154
155 char name[1];
156};
157
158
159
160
161
162
163
164
165
166
167
168
169
170static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
171{
172 struct fsl_ssi_private *ssi_private = dev_id;
173 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
174 irqreturn_t ret = IRQ_NONE;
175 __be32 sisr;
176 __be32 sisr2 = 0;
177
178
179
180
181
182 sisr = read_ssi(&ssi->sisr) & SIER_FLAGS;
183
184 if (sisr & CCSR_SSI_SISR_RFRC) {
185 ssi_private->stats.rfrc++;
186 sisr2 |= CCSR_SSI_SISR_RFRC;
187 ret = IRQ_HANDLED;
188 }
189
190 if (sisr & CCSR_SSI_SISR_TFRC) {
191 ssi_private->stats.tfrc++;
192 sisr2 |= CCSR_SSI_SISR_TFRC;
193 ret = IRQ_HANDLED;
194 }
195
196 if (sisr & CCSR_SSI_SISR_CMDAU) {
197 ssi_private->stats.cmdau++;
198 ret = IRQ_HANDLED;
199 }
200
201 if (sisr & CCSR_SSI_SISR_CMDDU) {
202 ssi_private->stats.cmddu++;
203 ret = IRQ_HANDLED;
204 }
205
206 if (sisr & CCSR_SSI_SISR_RXT) {
207 ssi_private->stats.rxt++;
208 ret = IRQ_HANDLED;
209 }
210
211 if (sisr & CCSR_SSI_SISR_RDR1) {
212 ssi_private->stats.rdr1++;
213 ret = IRQ_HANDLED;
214 }
215
216 if (sisr & CCSR_SSI_SISR_RDR0) {
217 ssi_private->stats.rdr0++;
218 ret = IRQ_HANDLED;
219 }
220
221 if (sisr & CCSR_SSI_SISR_TDE1) {
222 ssi_private->stats.tde1++;
223 ret = IRQ_HANDLED;
224 }
225
226 if (sisr & CCSR_SSI_SISR_TDE0) {
227 ssi_private->stats.tde0++;
228 ret = IRQ_HANDLED;
229 }
230
231 if (sisr & CCSR_SSI_SISR_ROE1) {
232 ssi_private->stats.roe1++;
233 sisr2 |= CCSR_SSI_SISR_ROE1;
234 ret = IRQ_HANDLED;
235 }
236
237 if (sisr & CCSR_SSI_SISR_ROE0) {
238 ssi_private->stats.roe0++;
239 sisr2 |= CCSR_SSI_SISR_ROE0;
240 ret = IRQ_HANDLED;
241 }
242
243 if (sisr & CCSR_SSI_SISR_TUE1) {
244 ssi_private->stats.tue1++;
245 sisr2 |= CCSR_SSI_SISR_TUE1;
246 ret = IRQ_HANDLED;
247 }
248
249 if (sisr & CCSR_SSI_SISR_TUE0) {
250 ssi_private->stats.tue0++;
251 sisr2 |= CCSR_SSI_SISR_TUE0;
252 ret = IRQ_HANDLED;
253 }
254
255 if (sisr & CCSR_SSI_SISR_TFS) {
256 ssi_private->stats.tfs++;
257 ret = IRQ_HANDLED;
258 }
259
260 if (sisr & CCSR_SSI_SISR_RFS) {
261 ssi_private->stats.rfs++;
262 ret = IRQ_HANDLED;
263 }
264
265 if (sisr & CCSR_SSI_SISR_TLS) {
266 ssi_private->stats.tls++;
267 ret = IRQ_HANDLED;
268 }
269
270 if (sisr & CCSR_SSI_SISR_RLS) {
271 ssi_private->stats.rls++;
272 ret = IRQ_HANDLED;
273 }
274
275 if (sisr & CCSR_SSI_SISR_RFF1) {
276 ssi_private->stats.rff1++;
277 ret = IRQ_HANDLED;
278 }
279
280 if (sisr & CCSR_SSI_SISR_RFF0) {
281 ssi_private->stats.rff0++;
282 ret = IRQ_HANDLED;
283 }
284
285 if (sisr & CCSR_SSI_SISR_TFE1) {
286 ssi_private->stats.tfe1++;
287 ret = IRQ_HANDLED;
288 }
289
290 if (sisr & CCSR_SSI_SISR_TFE0) {
291 ssi_private->stats.tfe0++;
292 ret = IRQ_HANDLED;
293 }
294
295
296 if (sisr2)
297 write_ssi(sisr2, &ssi->sisr);
298
299 return ret;
300}
301
302
303
304
305
306
307
308
309
310static int fsl_ssi_startup(struct snd_pcm_substream *substream,
311 struct snd_soc_dai *dai)
312{
313 struct snd_soc_pcm_runtime *rtd = substream->private_data;
314 struct fsl_ssi_private *ssi_private =
315 snd_soc_dai_get_drvdata(rtd->cpu_dai);
316 int synchronous = ssi_private->cpu_dai_drv.symmetric_rates;
317
318
319
320
321
322 if (!ssi_private->first_stream) {
323 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
324
325 ssi_private->first_stream = substream;
326
327
328
329
330
331
332 write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0);
333
334
335
336
337
338
339
340 write_ssi_mask(&ssi->scr,
341 CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_SYN,
342 CCSR_SSI_SCR_TFR_CLK_DIS | CCSR_SSI_SCR_I2S_MODE_SLAVE
343 | (synchronous ? CCSR_SSI_SCR_SYN : 0));
344
345 write_ssi(CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 |
346 CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TEFS |
347 CCSR_SSI_STCR_TSCKP, &ssi->stcr);
348
349 write_ssi(CCSR_SSI_SRCR_RXBIT0 | CCSR_SSI_SRCR_RFEN0 |
350 CCSR_SSI_SRCR_RFSI | CCSR_SSI_SRCR_REFS |
351 CCSR_SSI_SRCR_RSCKP, &ssi->srcr);
352
353
354
355
356
357
358
359 write_ssi(SIER_FLAGS, &ssi->sier);
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374 write_ssi(CCSR_SSI_SFCSR_TFWM0(ssi_private->fifo_depth - 2) |
375 CCSR_SSI_SFCSR_RFWM0(ssi_private->fifo_depth - 2),
376 &ssi->sfcsr);
377
378
379
380
381
382
383
384
385
386
387 } else {
388 if (synchronous) {
389 struct snd_pcm_runtime *first_runtime =
390 ssi_private->first_stream->runtime;
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410 if (!first_runtime->sample_bits) {
411 dev_err(substream->pcm->card->dev,
412 "set sample size in %s stream first\n",
413 substream->stream ==
414 SNDRV_PCM_STREAM_PLAYBACK
415 ? "capture" : "playback");
416 return -EAGAIN;
417 }
418
419 snd_pcm_hw_constraint_minmax(substream->runtime,
420 SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
421 first_runtime->sample_bits,
422 first_runtime->sample_bits);
423 }
424
425 ssi_private->second_stream = substream;
426 }
427
428 return 0;
429}
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
445 struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *cpu_dai)
446{
447 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
448 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
449 unsigned int sample_size =
450 snd_pcm_format_width(params_format(hw_params));
451 u32 wl = CCSR_SSI_SxCCR_WL(sample_size);
452 int enabled = read_ssi(&ssi->scr) & CCSR_SSI_SCR_SSIEN;
453
454
455
456
457
458 if (enabled && ssi_private->cpu_dai_drv.symmetric_rates)
459 return 0;
460
461
462
463
464
465
466
467
468
469
470
471
472 if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ||
473 ssi_private->cpu_dai_drv.symmetric_rates)
474 write_ssi_mask(&ssi->stccr, CCSR_SSI_SxCCR_WL_MASK, wl);
475 else
476 write_ssi_mask(&ssi->srccr, CCSR_SSI_SxCCR_WL_MASK, wl);
477
478 return 0;
479}
480
481
482
483
484
485
486
487
488
489
490static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
491 struct snd_soc_dai *dai)
492{
493 struct snd_soc_pcm_runtime *rtd = substream->private_data;
494 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai);
495 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
496
497 switch (cmd) {
498 case SNDRV_PCM_TRIGGER_START:
499 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
500 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
501 write_ssi_mask(&ssi->scr, 0,
502 CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_TE);
503 else
504 write_ssi_mask(&ssi->scr, 0,
505 CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_RE);
506 break;
507
508 case SNDRV_PCM_TRIGGER_STOP:
509 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
510 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
511 write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_TE, 0);
512 else
513 write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_RE, 0);
514 break;
515
516 default:
517 return -EINVAL;
518 }
519
520 return 0;
521}
522
523
524
525
526
527
528static void fsl_ssi_shutdown(struct snd_pcm_substream *substream,
529 struct snd_soc_dai *dai)
530{
531 struct snd_soc_pcm_runtime *rtd = substream->private_data;
532 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai);
533
534 if (ssi_private->first_stream == substream)
535 ssi_private->first_stream = ssi_private->second_stream;
536
537 ssi_private->second_stream = NULL;
538
539
540
541
542 if (!ssi_private->first_stream) {
543 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
544
545 write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0);
546 }
547}
548
549static int fsl_ssi_dai_probe(struct snd_soc_dai *dai)
550{
551 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(dai);
552
553 if (ssi_private->ssi_on_imx) {
554 dai->playback_dma_data = &ssi_private->dma_params_tx;
555 dai->capture_dma_data = &ssi_private->dma_params_rx;
556 }
557
558 return 0;
559}
560
561static const struct snd_soc_dai_ops fsl_ssi_dai_ops = {
562 .startup = fsl_ssi_startup,
563 .hw_params = fsl_ssi_hw_params,
564 .shutdown = fsl_ssi_shutdown,
565 .trigger = fsl_ssi_trigger,
566};
567
568
569static struct snd_soc_dai_driver fsl_ssi_dai_template = {
570 .probe = fsl_ssi_dai_probe,
571 .playback = {
572
573 .channels_min = 2,
574 .channels_max = 2,
575 .rates = FSLSSI_I2S_RATES,
576 .formats = FSLSSI_I2S_FORMATS,
577 },
578 .capture = {
579 .channels_min = 2,
580 .channels_max = 2,
581 .rates = FSLSSI_I2S_RATES,
582 .formats = FSLSSI_I2S_FORMATS,
583 },
584 .ops = &fsl_ssi_dai_ops,
585};
586
587static const struct snd_soc_component_driver fsl_ssi_component = {
588 .name = "fsl-ssi",
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
644static void make_lowercase(char *s)
645{
646 char *p = s;
647 char c;
648
649 while ((c = *p)) {
650 if ((c >= 'A') && (c <= 'Z'))
651 *p = c + ('a' - 'A');
652 p++;
653 }
654}
655
656static int fsl_ssi_probe(struct platform_device *pdev)
657{
658 struct fsl_ssi_private *ssi_private;
659 int ret = 0;
660 struct device_attribute *dev_attr = NULL;
661 struct device_node *np = pdev->dev.of_node;
662 const char *p, *sprop;
663 const uint32_t *iprop;
664 struct resource res;
665 char name[64];
666 bool shared;
667
668
669
670
671
672 if (!of_device_is_available(np))
673 return -ENODEV;
674
675
676 sprop = of_get_property(np, "fsl,mode", NULL);
677 if (!sprop || strcmp(sprop, "i2s-slave")) {
678 dev_notice(&pdev->dev, "mode %s is unsupported\n", sprop);
679 return -ENODEV;
680 }
681
682
683 p = strrchr(np->full_name, '/') + 1;
684 ssi_private = kzalloc(sizeof(struct fsl_ssi_private) + strlen(p),
685 GFP_KERNEL);
686 if (!ssi_private) {
687 dev_err(&pdev->dev, "could not allocate DAI object\n");
688 return -ENOMEM;
689 }
690
691 strcpy(ssi_private->name, p);
692
693
694 memcpy(&ssi_private->cpu_dai_drv, &fsl_ssi_dai_template,
695 sizeof(fsl_ssi_dai_template));
696 ssi_private->cpu_dai_drv.name = ssi_private->name;
697
698
699 ret = of_address_to_resource(np, 0, &res);
700 if (ret) {
701 dev_err(&pdev->dev, "could not determine device resources\n");
702 goto error_kmalloc;
703 }
704 ssi_private->ssi = of_iomap(np, 0);
705 if (!ssi_private->ssi) {
706 dev_err(&pdev->dev, "could not map device resources\n");
707 ret = -ENOMEM;
708 goto error_kmalloc;
709 }
710 ssi_private->ssi_phys = res.start;
711
712 ssi_private->irq = irq_of_parse_and_map(np, 0);
713 if (ssi_private->irq == NO_IRQ) {
714 dev_err(&pdev->dev, "no irq for node %s\n", np->full_name);
715 ret = -ENXIO;
716 goto error_iomap;
717 }
718
719
720 ret = request_irq(ssi_private->irq, fsl_ssi_isr, 0, ssi_private->name,
721 ssi_private);
722 if (ret < 0) {
723 dev_err(&pdev->dev, "could not claim irq %u\n", ssi_private->irq);
724 goto error_irqmap;
725 }
726
727
728 if (!of_find_property(np, "fsl,ssi-asynchronous", NULL))
729 ssi_private->cpu_dai_drv.symmetric_rates = 1;
730
731
732 iprop = of_get_property(np, "fsl,fifo-depth", NULL);
733 if (iprop)
734 ssi_private->fifo_depth = be32_to_cpup(iprop);
735 else
736
737 ssi_private->fifo_depth = 8;
738
739 if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx21-ssi")) {
740 u32 dma_events[2];
741 ssi_private->ssi_on_imx = true;
742
743 ssi_private->clk = clk_get(&pdev->dev, NULL);
744 if (IS_ERR(ssi_private->clk)) {
745 ret = PTR_ERR(ssi_private->clk);
746 dev_err(&pdev->dev, "could not get clock: %d\n", ret);
747 goto error_irq;
748 }
749 clk_prepare_enable(ssi_private->clk);
750
751
752
753
754
755 ssi_private->dma_params_tx.maxburst =
756 ssi_private->fifo_depth - 2;
757 ssi_private->dma_params_rx.maxburst =
758 ssi_private->fifo_depth - 2;
759 ssi_private->dma_params_tx.addr =
760 ssi_private->ssi_phys + offsetof(struct ccsr_ssi, stx0);
761 ssi_private->dma_params_rx.addr =
762 ssi_private->ssi_phys + offsetof(struct ccsr_ssi, srx0);
763 ssi_private->dma_params_tx.filter_data =
764 &ssi_private->filter_data_tx;
765 ssi_private->dma_params_rx.filter_data =
766 &ssi_private->filter_data_rx;
767
768
769
770
771 ret = of_property_read_u32_array(pdev->dev.of_node,
772 "fsl,ssi-dma-events", dma_events, 2);
773 if (ret) {
774 dev_err(&pdev->dev, "could not get dma events\n");
775 goto error_clk;
776 }
777
778 shared = of_device_is_compatible(of_get_parent(np),
779 "fsl,spba-bus");
780
781 imx_pcm_dma_params_init_data(&ssi_private->filter_data_tx,
782 dma_events[0], shared);
783 imx_pcm_dma_params_init_data(&ssi_private->filter_data_rx,
784 dma_events[1], shared);
785 }
786
787
788 dev_attr = &ssi_private->dev_attr;
789 sysfs_attr_init(&dev_attr->attr);
790 dev_attr->attr.name = "statistics";
791 dev_attr->attr.mode = S_IRUGO;
792 dev_attr->show = fsl_sysfs_ssi_show;
793
794 ret = device_create_file(&pdev->dev, dev_attr);
795 if (ret) {
796 dev_err(&pdev->dev, "could not create sysfs %s file\n",
797 ssi_private->dev_attr.attr.name);
798 goto error_irq;
799 }
800
801
802 dev_set_drvdata(&pdev->dev, ssi_private);
803
804 ret = snd_soc_register_component(&pdev->dev, &fsl_ssi_component,
805 &ssi_private->cpu_dai_drv, 1);
806 if (ret) {
807 dev_err(&pdev->dev, "failed to register DAI: %d\n", ret);
808 goto error_dev;
809 }
810
811 if (ssi_private->ssi_on_imx) {
812 ssi_private->imx_pcm_pdev =
813 platform_device_register_simple("imx-pcm-audio",
814 -1, NULL, 0);
815 if (IS_ERR(ssi_private->imx_pcm_pdev)) {
816 ret = PTR_ERR(ssi_private->imx_pcm_pdev);
817 goto error_dev;
818 }
819 }
820
821
822
823
824
825
826 if (!of_get_property(np, "codec-handle", NULL)) {
827 ssi_private->new_binding = true;
828 goto done;
829 }
830
831
832
833
834
835
836 sprop = of_get_property(of_find_node_by_path("/"), "compatible", NULL);
837
838 p = strrchr(sprop, ',');
839 if (p)
840 sprop = p + 1;
841 snprintf(name, sizeof(name), "snd-soc-%s", sprop);
842 make_lowercase(name);
843
844 ssi_private->pdev =
845 platform_device_register_data(&pdev->dev, name, 0, NULL, 0);
846 if (IS_ERR(ssi_private->pdev)) {
847 ret = PTR_ERR(ssi_private->pdev);
848 dev_err(&pdev->dev, "failed to register platform: %d\n", ret);
849 goto error_dai;
850 }
851
852done:
853 return 0;
854
855error_dai:
856 if (ssi_private->ssi_on_imx)
857 platform_device_unregister(ssi_private->imx_pcm_pdev);
858 snd_soc_unregister_component(&pdev->dev);
859
860error_dev:
861 dev_set_drvdata(&pdev->dev, NULL);
862 device_remove_file(&pdev->dev, dev_attr);
863
864error_clk:
865 if (ssi_private->ssi_on_imx) {
866 clk_disable_unprepare(ssi_private->clk);
867 clk_put(ssi_private->clk);
868 }
869
870error_irq:
871 free_irq(ssi_private->irq, ssi_private);
872
873error_irqmap:
874 irq_dispose_mapping(ssi_private->irq);
875
876error_iomap:
877 iounmap(ssi_private->ssi);
878
879error_kmalloc:
880 kfree(ssi_private);
881
882 return ret;
883}
884
885static int fsl_ssi_remove(struct platform_device *pdev)
886{
887 struct fsl_ssi_private *ssi_private = dev_get_drvdata(&pdev->dev);
888
889 if (!ssi_private->new_binding)
890 platform_device_unregister(ssi_private->pdev);
891 if (ssi_private->ssi_on_imx) {
892 platform_device_unregister(ssi_private->imx_pcm_pdev);
893 clk_disable_unprepare(ssi_private->clk);
894 clk_put(ssi_private->clk);
895 }
896 snd_soc_unregister_component(&pdev->dev);
897 device_remove_file(&pdev->dev, &ssi_private->dev_attr);
898
899 free_irq(ssi_private->irq, ssi_private);
900 irq_dispose_mapping(ssi_private->irq);
901
902 kfree(ssi_private);
903 dev_set_drvdata(&pdev->dev, NULL);
904
905 return 0;
906}
907
908static const struct of_device_id fsl_ssi_ids[] = {
909 { .compatible = "fsl,mpc8610-ssi", },
910 { .compatible = "fsl,imx21-ssi", },
911 {}
912};
913MODULE_DEVICE_TABLE(of, fsl_ssi_ids);
914
915static struct platform_driver fsl_ssi_driver = {
916 .driver = {
917 .name = "fsl-ssi-dai",
918 .owner = THIS_MODULE,
919 .of_match_table = fsl_ssi_ids,
920 },
921 .probe = fsl_ssi_probe,
922 .remove = fsl_ssi_remove,
923};
924
925module_platform_driver(fsl_ssi_driver);
926
927MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
928MODULE_DESCRIPTION("Freescale Synchronous Serial Interface (SSI) ASoC Driver");
929MODULE_LICENSE("GPL v2");
930