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