1
2
3
4
5
6#include <linux/module.h>
7#include <linux/init.h>
8#include <linux/of.h>
9#include <linux/of_device.h>
10#include <linux/platform_device.h>
11#include <linux/slab.h>
12#include <linux/dma-mapping.h>
13#include <linux/clk.h>
14#include <linux/clk-provider.h>
15#include <linux/delay.h>
16#include <linux/time.h>
17#include <sound/core.h>
18#include <sound/pcm.h>
19#include <sound/pcm_params.h>
20#include <sound/soc.h>
21
22#include "mxs-saif.h"
23
24#define MXS_SET_ADDR 0x4
25#define MXS_CLR_ADDR 0x8
26
27static struct mxs_saif *mxs_saif[2];
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47static int mxs_saif_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
48 int clk_id, unsigned int freq, int dir)
49{
50 struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai);
51
52 switch (clk_id) {
53 case MXS_SAIF_MCLK:
54 saif->mclk = freq;
55 break;
56 default:
57 return -EINVAL;
58 }
59 return 0;
60}
61
62
63
64
65
66
67
68static inline struct mxs_saif *mxs_saif_get_master(struct mxs_saif * saif)
69{
70 return mxs_saif[saif->master_id];
71}
72
73
74
75
76static int mxs_saif_set_clk(struct mxs_saif *saif,
77 unsigned int mclk,
78 unsigned int rate)
79{
80 u32 scr;
81 int ret;
82 struct mxs_saif *master_saif;
83
84 dev_dbg(saif->dev, "mclk %d rate %d\n", mclk, rate);
85
86
87 master_saif = mxs_saif_get_master(saif);
88 if (!master_saif)
89 return -EINVAL;
90
91 dev_dbg(saif->dev, "master saif%d\n", master_saif->id);
92
93
94 if (master_saif->ongoing && rate != master_saif->cur_rate) {
95 dev_err(saif->dev,
96 "can not change clock, master saif%d(rate %d) is ongoing\n",
97 master_saif->id, master_saif->cur_rate);
98 return -EINVAL;
99 }
100
101 scr = __raw_readl(master_saif->base + SAIF_CTRL);
102 scr &= ~BM_SAIF_CTRL_BITCLK_MULT_RATE;
103 scr &= ~BM_SAIF_CTRL_BITCLK_BASE_RATE;
104
105
106
107
108
109
110
111
112
113
114
115 ret = clk_prepare_enable(master_saif->clk);
116 if (ret)
117 return ret;
118
119 if (master_saif->mclk_in_use) {
120 switch (mclk / rate) {
121 case 32:
122 case 64:
123 case 128:
124 case 256:
125 case 512:
126 scr &= ~BM_SAIF_CTRL_BITCLK_BASE_RATE;
127 ret = clk_set_rate(master_saif->clk, 512 * rate);
128 break;
129 case 48:
130 case 96:
131 case 192:
132 case 384:
133 scr |= BM_SAIF_CTRL_BITCLK_BASE_RATE;
134 ret = clk_set_rate(master_saif->clk, 384 * rate);
135 break;
136 default:
137
138 clk_disable_unprepare(master_saif->clk);
139 return -EINVAL;
140 }
141 } else {
142 ret = clk_set_rate(master_saif->clk, 512 * rate);
143 scr &= ~BM_SAIF_CTRL_BITCLK_BASE_RATE;
144 }
145
146 clk_disable_unprepare(master_saif->clk);
147
148 if (ret)
149 return ret;
150
151 master_saif->cur_rate = rate;
152
153 if (!master_saif->mclk_in_use) {
154 __raw_writel(scr, master_saif->base + SAIF_CTRL);
155 return 0;
156 }
157
158
159
160
161
162
163
164 switch (mclk / rate) {
165 case 32:
166 scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(4);
167 break;
168 case 64:
169 scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(3);
170 break;
171 case 128:
172 scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(2);
173 break;
174 case 256:
175 scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(1);
176 break;
177 case 512:
178 scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(0);
179 break;
180 case 48:
181 scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(3);
182 break;
183 case 96:
184 scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(2);
185 break;
186 case 192:
187 scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(1);
188 break;
189 case 384:
190 scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(0);
191 break;
192 default:
193 return -EINVAL;
194 }
195
196 __raw_writel(scr, master_saif->base + SAIF_CTRL);
197
198 return 0;
199}
200
201
202
203
204int mxs_saif_put_mclk(unsigned int saif_id)
205{
206 struct mxs_saif *saif = mxs_saif[saif_id];
207 u32 stat;
208
209 if (!saif)
210 return -EINVAL;
211
212 stat = __raw_readl(saif->base + SAIF_STAT);
213 if (stat & BM_SAIF_STAT_BUSY) {
214 dev_err(saif->dev, "error: busy\n");
215 return -EBUSY;
216 }
217
218 clk_disable_unprepare(saif->clk);
219
220
221 __raw_writel(BM_SAIF_CTRL_CLKGATE,
222 saif->base + SAIF_CTRL + MXS_SET_ADDR);
223 __raw_writel(BM_SAIF_CTRL_RUN,
224 saif->base + SAIF_CTRL + MXS_CLR_ADDR);
225
226 saif->mclk_in_use = 0;
227 return 0;
228}
229EXPORT_SYMBOL_GPL(mxs_saif_put_mclk);
230
231
232
233
234
235
236
237int mxs_saif_get_mclk(unsigned int saif_id, unsigned int mclk,
238 unsigned int rate)
239{
240 struct mxs_saif *saif = mxs_saif[saif_id];
241 u32 stat;
242 int ret;
243 struct mxs_saif *master_saif;
244
245 if (!saif)
246 return -EINVAL;
247
248
249 __raw_writel(BM_SAIF_CTRL_SFTRST,
250 saif->base + SAIF_CTRL + MXS_CLR_ADDR);
251
252
253 __raw_writel(BM_SAIF_CTRL_CLKGATE,
254 saif->base + SAIF_CTRL + MXS_CLR_ADDR);
255
256 master_saif = mxs_saif_get_master(saif);
257 if (saif != master_saif) {
258 dev_err(saif->dev, "can not get mclk from a non-master saif\n");
259 return -EINVAL;
260 }
261
262 stat = __raw_readl(saif->base + SAIF_STAT);
263 if (stat & BM_SAIF_STAT_BUSY) {
264 dev_err(saif->dev, "error: busy\n");
265 return -EBUSY;
266 }
267
268 saif->mclk_in_use = 1;
269 ret = mxs_saif_set_clk(saif, mclk, rate);
270 if (ret)
271 return ret;
272
273 ret = clk_prepare_enable(saif->clk);
274 if (ret)
275 return ret;
276
277
278 __raw_writel(BM_SAIF_CTRL_RUN,
279 saif->base + SAIF_CTRL + MXS_SET_ADDR);
280
281 return 0;
282}
283EXPORT_SYMBOL_GPL(mxs_saif_get_mclk);
284
285
286
287
288
289static int mxs_saif_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
290{
291 u32 scr, stat;
292 u32 scr0;
293 struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai);
294
295 stat = __raw_readl(saif->base + SAIF_STAT);
296 if (stat & BM_SAIF_STAT_BUSY) {
297 dev_err(cpu_dai->dev, "error: busy\n");
298 return -EBUSY;
299 }
300
301
302
303
304 if (saif->id != saif->master_id) {
305 __raw_writel(BM_SAIF_CTRL_SFTRST,
306 saif->base + SAIF_CTRL + MXS_CLR_ADDR);
307 __raw_writel(BM_SAIF_CTRL_CLKGATE,
308 saif->base + SAIF_CTRL + MXS_CLR_ADDR);
309 }
310
311 scr0 = __raw_readl(saif->base + SAIF_CTRL);
312 scr0 = scr0 & ~BM_SAIF_CTRL_BITCLK_EDGE & ~BM_SAIF_CTRL_LRCLK_POLARITY \
313 & ~BM_SAIF_CTRL_JUSTIFY & ~BM_SAIF_CTRL_DELAY;
314 scr = 0;
315
316
317 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
318 case SND_SOC_DAIFMT_I2S:
319
320 scr |= BM_SAIF_CTRL_DELAY;
321 scr &= ~BM_SAIF_CTRL_LRCLK_POLARITY;
322 break;
323 case SND_SOC_DAIFMT_LEFT_J:
324
325 scr &= ~BM_SAIF_CTRL_DELAY;
326 scr &= ~BM_SAIF_CTRL_LRCLK_POLARITY;
327 scr &= ~BM_SAIF_CTRL_JUSTIFY;
328 break;
329 default:
330 return -EINVAL;
331 }
332
333
334 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
335 case SND_SOC_DAIFMT_IB_IF:
336 scr |= BM_SAIF_CTRL_BITCLK_EDGE;
337 scr |= BM_SAIF_CTRL_LRCLK_POLARITY;
338 break;
339 case SND_SOC_DAIFMT_IB_NF:
340 scr |= BM_SAIF_CTRL_BITCLK_EDGE;
341 scr &= ~BM_SAIF_CTRL_LRCLK_POLARITY;
342 break;
343 case SND_SOC_DAIFMT_NB_IF:
344 scr &= ~BM_SAIF_CTRL_BITCLK_EDGE;
345 scr |= BM_SAIF_CTRL_LRCLK_POLARITY;
346 break;
347 case SND_SOC_DAIFMT_NB_NF:
348 scr &= ~BM_SAIF_CTRL_BITCLK_EDGE;
349 scr &= ~BM_SAIF_CTRL_LRCLK_POLARITY;
350 break;
351 }
352
353
354
355
356
357
358
359
360 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
361 case SND_SOC_DAIFMT_CBS_CFS:
362 if (saif->id == saif->master_id)
363 scr &= ~BM_SAIF_CTRL_SLAVE_MODE;
364 else
365 scr |= BM_SAIF_CTRL_SLAVE_MODE;
366
367 __raw_writel(scr | scr0, saif->base + SAIF_CTRL);
368 break;
369 default:
370 return -EINVAL;
371 }
372
373 return 0;
374}
375
376static int mxs_saif_startup(struct snd_pcm_substream *substream,
377 struct snd_soc_dai *cpu_dai)
378{
379 struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai);
380 int ret;
381
382
383 saif->fifo_underrun = 0;
384 saif->fifo_overrun = 0;
385
386
387 __raw_writel(BM_SAIF_CTRL_SFTRST,
388 saif->base + SAIF_CTRL + MXS_CLR_ADDR);
389
390
391 __raw_writel(BM_SAIF_CTRL_CLKGATE,
392 saif->base + SAIF_CTRL + MXS_CLR_ADDR);
393
394 ret = clk_prepare(saif->clk);
395 if (ret)
396 return ret;
397
398 return 0;
399}
400
401static void mxs_saif_shutdown(struct snd_pcm_substream *substream,
402 struct snd_soc_dai *cpu_dai)
403{
404 struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai);
405
406 clk_unprepare(saif->clk);
407}
408
409
410
411
412
413static int mxs_saif_hw_params(struct snd_pcm_substream *substream,
414 struct snd_pcm_hw_params *params,
415 struct snd_soc_dai *cpu_dai)
416{
417 struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai);
418 struct mxs_saif *master_saif;
419 u32 scr, stat;
420 int ret;
421
422 master_saif = mxs_saif_get_master(saif);
423 if (!master_saif)
424 return -EINVAL;
425
426
427 if (!saif->mclk && saif->mclk_in_use) {
428 dev_err(cpu_dai->dev, "set mclk first\n");
429 return -EINVAL;
430 }
431
432 stat = __raw_readl(saif->base + SAIF_STAT);
433 if (!saif->mclk_in_use && (stat & BM_SAIF_STAT_BUSY)) {
434 dev_err(cpu_dai->dev, "error: busy\n");
435 return -EBUSY;
436 }
437
438
439
440
441
442
443 ret = mxs_saif_set_clk(saif, saif->mclk, params_rate(params));
444 if (ret) {
445 dev_err(cpu_dai->dev, "unable to get proper clk\n");
446 return ret;
447 }
448
449 if (saif != master_saif) {
450
451
452
453
454
455
456
457 clk_enable(saif->clk);
458 ret = clk_set_rate(saif->clk, 24000000);
459 clk_disable(saif->clk);
460 if (ret)
461 return ret;
462
463 ret = clk_prepare(master_saif->clk);
464 if (ret)
465 return ret;
466 }
467
468 scr = __raw_readl(saif->base + SAIF_CTRL);
469
470 scr &= ~BM_SAIF_CTRL_WORD_LENGTH;
471 scr &= ~BM_SAIF_CTRL_BITCLK_48XFS_ENABLE;
472 switch (params_format(params)) {
473 case SNDRV_PCM_FORMAT_S16_LE:
474 scr |= BF_SAIF_CTRL_WORD_LENGTH(0);
475 break;
476 case SNDRV_PCM_FORMAT_S20_3LE:
477 scr |= BF_SAIF_CTRL_WORD_LENGTH(4);
478 scr |= BM_SAIF_CTRL_BITCLK_48XFS_ENABLE;
479 break;
480 case SNDRV_PCM_FORMAT_S24_LE:
481 scr |= BF_SAIF_CTRL_WORD_LENGTH(8);
482 scr |= BM_SAIF_CTRL_BITCLK_48XFS_ENABLE;
483 break;
484 default:
485 return -EINVAL;
486 }
487
488
489 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
490
491 scr &= ~BM_SAIF_CTRL_READ_MODE;
492 } else {
493
494 scr |= BM_SAIF_CTRL_READ_MODE;
495 }
496
497 __raw_writel(scr, saif->base + SAIF_CTRL);
498 return 0;
499}
500
501static int mxs_saif_prepare(struct snd_pcm_substream *substream,
502 struct snd_soc_dai *cpu_dai)
503{
504 struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai);
505
506
507 __raw_writel(BM_SAIF_CTRL_FIFO_ERROR_IRQ_EN,
508 saif->base + SAIF_CTRL + MXS_SET_ADDR);
509
510 return 0;
511}
512
513static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd,
514 struct snd_soc_dai *cpu_dai)
515{
516 struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai);
517 struct mxs_saif *master_saif;
518 u32 delay;
519 int ret;
520
521 master_saif = mxs_saif_get_master(saif);
522 if (!master_saif)
523 return -EINVAL;
524
525 switch (cmd) {
526 case SNDRV_PCM_TRIGGER_START:
527 case SNDRV_PCM_TRIGGER_RESUME:
528 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
529 if (saif->state == MXS_SAIF_STATE_RUNNING)
530 return 0;
531
532 dev_dbg(cpu_dai->dev, "start\n");
533
534 ret = clk_enable(master_saif->clk);
535 if (ret) {
536 dev_err(saif->dev, "Failed to enable master clock\n");
537 return ret;
538 }
539
540
541
542
543
544 if (saif != master_saif) {
545 ret = clk_enable(saif->clk);
546 if (ret) {
547 dev_err(saif->dev, "Failed to enable master clock\n");
548 clk_disable(master_saif->clk);
549 return ret;
550 }
551
552 __raw_writel(BM_SAIF_CTRL_RUN,
553 saif->base + SAIF_CTRL + MXS_SET_ADDR);
554 }
555
556 if (!master_saif->mclk_in_use)
557 __raw_writel(BM_SAIF_CTRL_RUN,
558 master_saif->base + SAIF_CTRL + MXS_SET_ADDR);
559
560 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
561
562
563
564
565
566
567
568 __raw_writel(0, saif->base + SAIF_DATA);
569 __raw_writel(0, saif->base + SAIF_DATA);
570 } else {
571
572
573
574
575
576
577
578 __raw_readl(saif->base + SAIF_DATA);
579 __raw_readl(saif->base + SAIF_DATA);
580 }
581
582 master_saif->ongoing = 1;
583 saif->state = MXS_SAIF_STATE_RUNNING;
584
585 dev_dbg(saif->dev, "CTRL 0x%x STAT 0x%x\n",
586 __raw_readl(saif->base + SAIF_CTRL),
587 __raw_readl(saif->base + SAIF_STAT));
588
589 dev_dbg(master_saif->dev, "CTRL 0x%x STAT 0x%x\n",
590 __raw_readl(master_saif->base + SAIF_CTRL),
591 __raw_readl(master_saif->base + SAIF_STAT));
592 break;
593 case SNDRV_PCM_TRIGGER_SUSPEND:
594 case SNDRV_PCM_TRIGGER_STOP:
595 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
596 if (saif->state == MXS_SAIF_STATE_STOPPED)
597 return 0;
598
599 dev_dbg(cpu_dai->dev, "stop\n");
600
601
602 delay = USEC_PER_SEC / master_saif->cur_rate;
603
604 if (!master_saif->mclk_in_use) {
605 __raw_writel(BM_SAIF_CTRL_RUN,
606 master_saif->base + SAIF_CTRL + MXS_CLR_ADDR);
607 udelay(delay);
608 }
609 clk_disable(master_saif->clk);
610
611 if (saif != master_saif) {
612 __raw_writel(BM_SAIF_CTRL_RUN,
613 saif->base + SAIF_CTRL + MXS_CLR_ADDR);
614 udelay(delay);
615 clk_disable(saif->clk);
616 }
617
618 master_saif->ongoing = 0;
619 saif->state = MXS_SAIF_STATE_STOPPED;
620
621 break;
622 default:
623 return -EINVAL;
624 }
625
626 return 0;
627}
628
629#define MXS_SAIF_RATES SNDRV_PCM_RATE_8000_192000
630#define MXS_SAIF_FORMATS \
631 (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
632 SNDRV_PCM_FMTBIT_S24_LE)
633
634static const struct snd_soc_dai_ops mxs_saif_dai_ops = {
635 .startup = mxs_saif_startup,
636 .shutdown = mxs_saif_shutdown,
637 .trigger = mxs_saif_trigger,
638 .prepare = mxs_saif_prepare,
639 .hw_params = mxs_saif_hw_params,
640 .set_sysclk = mxs_saif_set_dai_sysclk,
641 .set_fmt = mxs_saif_set_dai_fmt,
642};
643
644static int mxs_saif_dai_probe(struct snd_soc_dai *dai)
645{
646 struct mxs_saif *saif = dev_get_drvdata(dai->dev);
647
648 snd_soc_dai_set_drvdata(dai, saif);
649
650 return 0;
651}
652
653static struct snd_soc_dai_driver mxs_saif_dai = {
654 .name = "mxs-saif",
655 .probe = mxs_saif_dai_probe,
656 .playback = {
657 .channels_min = 2,
658 .channels_max = 2,
659 .rates = MXS_SAIF_RATES,
660 .formats = MXS_SAIF_FORMATS,
661 },
662 .capture = {
663 .channels_min = 2,
664 .channels_max = 2,
665 .rates = MXS_SAIF_RATES,
666 .formats = MXS_SAIF_FORMATS,
667 },
668 .ops = &mxs_saif_dai_ops,
669};
670
671static const struct snd_soc_component_driver mxs_saif_component = {
672 .name = "mxs-saif",
673};
674
675static irqreturn_t mxs_saif_irq(int irq, void *dev_id)
676{
677 struct mxs_saif *saif = dev_id;
678 unsigned int stat;
679
680 stat = __raw_readl(saif->base + SAIF_STAT);
681 if (!(stat & (BM_SAIF_STAT_FIFO_UNDERFLOW_IRQ |
682 BM_SAIF_STAT_FIFO_OVERFLOW_IRQ)))
683 return IRQ_NONE;
684
685 if (stat & BM_SAIF_STAT_FIFO_UNDERFLOW_IRQ) {
686 dev_dbg(saif->dev, "underrun!!! %d\n", ++saif->fifo_underrun);
687 __raw_writel(BM_SAIF_STAT_FIFO_UNDERFLOW_IRQ,
688 saif->base + SAIF_STAT + MXS_CLR_ADDR);
689 }
690
691 if (stat & BM_SAIF_STAT_FIFO_OVERFLOW_IRQ) {
692 dev_dbg(saif->dev, "overrun!!! %d\n", ++saif->fifo_overrun);
693 __raw_writel(BM_SAIF_STAT_FIFO_OVERFLOW_IRQ,
694 saif->base + SAIF_STAT + MXS_CLR_ADDR);
695 }
696
697 dev_dbg(saif->dev, "SAIF_CTRL %x SAIF_STAT %x\n",
698 __raw_readl(saif->base + SAIF_CTRL),
699 __raw_readl(saif->base + SAIF_STAT));
700
701 return IRQ_HANDLED;
702}
703
704static int mxs_saif_mclk_init(struct platform_device *pdev)
705{
706 struct mxs_saif *saif = platform_get_drvdata(pdev);
707 struct device_node *np = pdev->dev.of_node;
708 struct clk *clk;
709 int ret;
710
711 clk = clk_register_divider(&pdev->dev, "mxs_saif_mclk",
712 __clk_get_name(saif->clk), 0,
713 saif->base + SAIF_CTRL,
714 BP_SAIF_CTRL_BITCLK_MULT_RATE, 3,
715 0, NULL);
716 if (IS_ERR(clk)) {
717 ret = PTR_ERR(clk);
718 if (ret == -EEXIST)
719 return 0;
720 dev_err(&pdev->dev, "failed to register mclk: %d\n", ret);
721 return PTR_ERR(clk);
722 }
723
724 ret = of_clk_add_provider(np, of_clk_src_simple_get, clk);
725 if (ret)
726 return ret;
727
728 return 0;
729}
730
731static int mxs_saif_probe(struct platform_device *pdev)
732{
733 struct device_node *np = pdev->dev.of_node;
734 struct mxs_saif *saif;
735 int irq, ret;
736 struct device_node *master;
737
738 saif = devm_kzalloc(&pdev->dev, sizeof(*saif), GFP_KERNEL);
739 if (!saif)
740 return -ENOMEM;
741
742 ret = of_alias_get_id(np, "saif");
743 if (ret < 0)
744 return ret;
745 else
746 saif->id = ret;
747
748 if (saif->id >= ARRAY_SIZE(mxs_saif)) {
749 dev_err(&pdev->dev, "get wrong saif id\n");
750 return -EINVAL;
751 }
752
753
754
755
756
757
758 master = of_parse_phandle(np, "fsl,saif-master", 0);
759 if (!master) {
760 saif->master_id = saif->id;
761 } else {
762 ret = of_alias_get_id(master, "saif");
763 if (ret < 0)
764 return ret;
765 else
766 saif->master_id = ret;
767
768 if (saif->master_id >= ARRAY_SIZE(mxs_saif)) {
769 dev_err(&pdev->dev, "get wrong master id\n");
770 return -EINVAL;
771 }
772 }
773
774 mxs_saif[saif->id] = saif;
775
776 saif->clk = devm_clk_get(&pdev->dev, NULL);
777 if (IS_ERR(saif->clk)) {
778 ret = PTR_ERR(saif->clk);
779 dev_err(&pdev->dev, "Cannot get the clock: %d\n",
780 ret);
781 return ret;
782 }
783
784 saif->base = devm_platform_ioremap_resource(pdev, 0);
785 if (IS_ERR(saif->base))
786 return PTR_ERR(saif->base);
787
788 irq = platform_get_irq(pdev, 0);
789 if (irq < 0)
790 return irq;
791
792 saif->dev = &pdev->dev;
793 ret = devm_request_irq(&pdev->dev, irq, mxs_saif_irq, 0,
794 dev_name(&pdev->dev), saif);
795 if (ret) {
796 dev_err(&pdev->dev, "failed to request irq\n");
797 return ret;
798 }
799
800 platform_set_drvdata(pdev, saif);
801
802
803 if (saif->id == 0) {
804 ret = mxs_saif_mclk_init(pdev);
805 if (ret)
806 dev_warn(&pdev->dev, "failed to init clocks\n");
807 }
808
809 ret = devm_snd_soc_register_component(&pdev->dev, &mxs_saif_component,
810 &mxs_saif_dai, 1);
811 if (ret) {
812 dev_err(&pdev->dev, "register DAI failed\n");
813 return ret;
814 }
815
816 ret = mxs_pcm_platform_register(&pdev->dev);
817 if (ret) {
818 dev_err(&pdev->dev, "register PCM failed: %d\n", ret);
819 return ret;
820 }
821
822 return 0;
823}
824
825static const struct of_device_id mxs_saif_dt_ids[] = {
826 { .compatible = "fsl,imx28-saif", },
827 { }
828};
829MODULE_DEVICE_TABLE(of, mxs_saif_dt_ids);
830
831static struct platform_driver mxs_saif_driver = {
832 .probe = mxs_saif_probe,
833
834 .driver = {
835 .name = "mxs-saif",
836 .of_match_table = mxs_saif_dt_ids,
837 },
838};
839
840module_platform_driver(mxs_saif_driver);
841
842MODULE_AUTHOR("Freescale Semiconductor, Inc.");
843MODULE_DESCRIPTION("MXS ASoC SAIF driver");
844MODULE_LICENSE("GPL");
845MODULE_ALIAS("platform:mxs-saif");
846