1
2
3
4
5
6
7
8
9
10
11
12
13#include <linux/module.h>
14#include <linux/init.h>
15#include <linux/platform_device.h>
16#include <linux/dma-mapping.h>
17#include <linux/interrupt.h>
18#include <linux/delay.h>
19#include <linux/gfp.h>
20#include <linux/of_address.h>
21#include <linux/of_irq.h>
22#include <linux/of_platform.h>
23#include <linux/list.h>
24#include <linux/slab.h>
25
26#include <sound/core.h>
27#include <sound/pcm.h>
28#include <sound/pcm_params.h>
29#include <sound/soc.h>
30
31#include <asm/io.h>
32
33#include "fsl_dma.h"
34#include "fsl_ssi.h"
35
36#define DRV_NAME "fsl_dma"
37
38
39
40
41
42#define FSLDMA_PCM_FORMATS (SNDRV_PCM_FMTBIT_S8 | \
43 SNDRV_PCM_FMTBIT_U8 | \
44 SNDRV_PCM_FMTBIT_S16_LE | \
45 SNDRV_PCM_FMTBIT_S16_BE | \
46 SNDRV_PCM_FMTBIT_U16_LE | \
47 SNDRV_PCM_FMTBIT_U16_BE | \
48 SNDRV_PCM_FMTBIT_S24_LE | \
49 SNDRV_PCM_FMTBIT_S24_BE | \
50 SNDRV_PCM_FMTBIT_U24_LE | \
51 SNDRV_PCM_FMTBIT_U24_BE | \
52 SNDRV_PCM_FMTBIT_S32_LE | \
53 SNDRV_PCM_FMTBIT_S32_BE | \
54 SNDRV_PCM_FMTBIT_U32_LE | \
55 SNDRV_PCM_FMTBIT_U32_BE)
56struct dma_object {
57 struct snd_soc_component_driver dai;
58 dma_addr_t ssi_stx_phys;
59 dma_addr_t ssi_srx_phys;
60 unsigned int ssi_fifo_depth;
61 struct ccsr_dma_channel __iomem *channel;
62 unsigned int irq;
63 bool assigned;
64};
65
66
67
68
69
70#define NUM_DMA_LINKS 2
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93struct fsl_dma_private {
94 struct fsl_dma_link_descriptor link[NUM_DMA_LINKS];
95 struct ccsr_dma_channel __iomem *dma_channel;
96 unsigned int irq;
97 struct snd_pcm_substream *substream;
98 dma_addr_t ssi_sxx_phys;
99 unsigned int ssi_fifo_depth;
100 dma_addr_t ld_buf_phys;
101 unsigned int current_link;
102 dma_addr_t dma_buf_phys;
103 dma_addr_t dma_buf_next;
104 dma_addr_t dma_buf_end;
105 size_t period_size;
106 unsigned int num_periods;
107};
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128static const struct snd_pcm_hardware fsl_dma_hardware = {
129
130 .info = SNDRV_PCM_INFO_INTERLEAVED |
131 SNDRV_PCM_INFO_MMAP |
132 SNDRV_PCM_INFO_MMAP_VALID |
133 SNDRV_PCM_INFO_JOINT_DUPLEX |
134 SNDRV_PCM_INFO_PAUSE,
135 .formats = FSLDMA_PCM_FORMATS,
136 .period_bytes_min = 512,
137 .period_bytes_max = (u32) -1,
138 .periods_min = NUM_DMA_LINKS,
139 .periods_max = (unsigned int) -1,
140 .buffer_bytes_max = 128 * 1024,
141};
142
143
144
145
146
147
148
149static void fsl_dma_abort_stream(struct snd_pcm_substream *substream)
150{
151 snd_pcm_stop_xrun(substream);
152}
153
154
155
156
157
158
159
160static void fsl_dma_update_pointers(struct fsl_dma_private *dma_private)
161{
162 struct fsl_dma_link_descriptor *link =
163 &dma_private->link[dma_private->current_link];
164
165
166
167
168
169 if (dma_private->substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
170 link->source_addr = cpu_to_be32(dma_private->dma_buf_next);
171#ifdef CONFIG_PHYS_64BIT
172 link->source_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP |
173 upper_32_bits(dma_private->dma_buf_next));
174#endif
175 } else {
176 link->dest_addr = cpu_to_be32(dma_private->dma_buf_next);
177#ifdef CONFIG_PHYS_64BIT
178 link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP |
179 upper_32_bits(dma_private->dma_buf_next));
180#endif
181 }
182
183
184 dma_private->dma_buf_next += dma_private->period_size;
185
186 if (dma_private->dma_buf_next >= dma_private->dma_buf_end)
187 dma_private->dma_buf_next = dma_private->dma_buf_phys;
188
189 if (++dma_private->current_link >= NUM_DMA_LINKS)
190 dma_private->current_link = 0;
191}
192
193
194
195
196
197
198
199static irqreturn_t fsl_dma_isr(int irq, void *dev_id)
200{
201 struct fsl_dma_private *dma_private = dev_id;
202 struct snd_pcm_substream *substream = dma_private->substream;
203 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
204 struct device *dev = rtd->dev;
205 struct ccsr_dma_channel __iomem *dma_channel = dma_private->dma_channel;
206 irqreturn_t ret = IRQ_NONE;
207 u32 sr, sr2 = 0;
208
209
210
211
212 sr = in_be32(&dma_channel->sr);
213
214 if (sr & CCSR_DMA_SR_TE) {
215 dev_err(dev, "dma transmit error\n");
216 fsl_dma_abort_stream(substream);
217 sr2 |= CCSR_DMA_SR_TE;
218 ret = IRQ_HANDLED;
219 }
220
221 if (sr & CCSR_DMA_SR_CH)
222 ret = IRQ_HANDLED;
223
224 if (sr & CCSR_DMA_SR_PE) {
225 dev_err(dev, "dma programming error\n");
226 fsl_dma_abort_stream(substream);
227 sr2 |= CCSR_DMA_SR_PE;
228 ret = IRQ_HANDLED;
229 }
230
231 if (sr & CCSR_DMA_SR_EOLNI) {
232 sr2 |= CCSR_DMA_SR_EOLNI;
233 ret = IRQ_HANDLED;
234 }
235
236 if (sr & CCSR_DMA_SR_CB)
237 ret = IRQ_HANDLED;
238
239 if (sr & CCSR_DMA_SR_EOSI) {
240
241 snd_pcm_period_elapsed(substream);
242
243
244
245
246
247
248 if (dma_private->num_periods != NUM_DMA_LINKS)
249 fsl_dma_update_pointers(dma_private);
250
251 sr2 |= CCSR_DMA_SR_EOSI;
252 ret = IRQ_HANDLED;
253 }
254
255 if (sr & CCSR_DMA_SR_EOLSI) {
256 sr2 |= CCSR_DMA_SR_EOLSI;
257 ret = IRQ_HANDLED;
258 }
259
260
261 if (sr2)
262 out_be32(&dma_channel->sr, sr2);
263
264 return ret;
265}
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282static int fsl_dma_new(struct snd_soc_component *component,
283 struct snd_soc_pcm_runtime *rtd)
284{
285 struct snd_card *card = rtd->card->snd_card;
286 struct snd_pcm *pcm = rtd->pcm;
287 int ret;
288
289 ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(36));
290 if (ret)
291 return ret;
292
293
294
295
296
297 if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
298 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev,
299 fsl_dma_hardware.buffer_bytes_max,
300 &pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->dma_buffer);
301 if (ret) {
302 dev_err(card->dev, "can't alloc playback dma buffer\n");
303 return ret;
304 }
305 }
306
307 if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
308 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev,
309 fsl_dma_hardware.buffer_bytes_max,
310 &pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->dma_buffer);
311 if (ret) {
312 dev_err(card->dev, "can't alloc capture dma buffer\n");
313 snd_dma_free_pages(&pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->dma_buffer);
314 return ret;
315 }
316 }
317
318 return 0;
319}
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383static int fsl_dma_open(struct snd_soc_component *component,
384 struct snd_pcm_substream *substream)
385{
386 struct snd_pcm_runtime *runtime = substream->runtime;
387 struct device *dev = component->dev;
388 struct dma_object *dma =
389 container_of(component->driver, struct dma_object, dai);
390 struct fsl_dma_private *dma_private;
391 struct ccsr_dma_channel __iomem *dma_channel;
392 dma_addr_t ld_buf_phys;
393 u64 temp_link;
394 u32 mr;
395 int ret = 0;
396 unsigned int i;
397
398
399
400
401
402
403 ret = snd_pcm_hw_constraint_integer(runtime,
404 SNDRV_PCM_HW_PARAM_PERIODS);
405 if (ret < 0) {
406 dev_err(dev, "invalid buffer size\n");
407 return ret;
408 }
409
410 if (dma->assigned) {
411 dev_err(dev, "dma channel already assigned\n");
412 return -EBUSY;
413 }
414
415 dma_private = dma_alloc_coherent(dev, sizeof(struct fsl_dma_private),
416 &ld_buf_phys, GFP_KERNEL);
417 if (!dma_private) {
418 dev_err(dev, "can't allocate dma private data\n");
419 return -ENOMEM;
420 }
421 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
422 dma_private->ssi_sxx_phys = dma->ssi_stx_phys;
423 else
424 dma_private->ssi_sxx_phys = dma->ssi_srx_phys;
425
426 dma_private->ssi_fifo_depth = dma->ssi_fifo_depth;
427 dma_private->dma_channel = dma->channel;
428 dma_private->irq = dma->irq;
429 dma_private->substream = substream;
430 dma_private->ld_buf_phys = ld_buf_phys;
431 dma_private->dma_buf_phys = substream->dma_buffer.addr;
432
433 ret = request_irq(dma_private->irq, fsl_dma_isr, 0, "fsldma-audio",
434 dma_private);
435 if (ret) {
436 dev_err(dev, "can't register ISR for IRQ %u (ret=%i)\n",
437 dma_private->irq, ret);
438 dma_free_coherent(dev, sizeof(struct fsl_dma_private),
439 dma_private, dma_private->ld_buf_phys);
440 return ret;
441 }
442
443 dma->assigned = true;
444
445 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
446 snd_soc_set_runtime_hwparams(substream, &fsl_dma_hardware);
447 runtime->private_data = dma_private;
448
449
450
451 dma_channel = dma_private->dma_channel;
452
453 temp_link = dma_private->ld_buf_phys +
454 sizeof(struct fsl_dma_link_descriptor);
455
456 for (i = 0; i < NUM_DMA_LINKS; i++) {
457 dma_private->link[i].next = cpu_to_be64(temp_link);
458
459 temp_link += sizeof(struct fsl_dma_link_descriptor);
460 }
461
462 dma_private->link[i - 1].next = cpu_to_be64(dma_private->ld_buf_phys);
463
464
465 out_be32(&dma_channel->clndar,
466 CCSR_DMA_CLNDAR_ADDR(dma_private->ld_buf_phys));
467 out_be32(&dma_channel->eclndar,
468 CCSR_DMA_ECLNDAR_ADDR(dma_private->ld_buf_phys));
469
470
471 out_be32(&dma_channel->bcr, 0);
472
473
474
475
476
477 mr = in_be32(&dma_channel->mr) &
478 ~(CCSR_DMA_MR_CA | CCSR_DMA_MR_DAHE | CCSR_DMA_MR_SAHE);
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495 mr |= CCSR_DMA_MR_EOSIE | CCSR_DMA_MR_EIE | CCSR_DMA_MR_EMP_EN |
496 CCSR_DMA_MR_EMS_EN;
497
498
499
500 mr |= (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
501 CCSR_DMA_MR_DAHE : CCSR_DMA_MR_SAHE;
502
503 out_be32(&dma_channel->mr, mr);
504
505 return 0;
506}
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532static int fsl_dma_hw_params(struct snd_soc_component *component,
533 struct snd_pcm_substream *substream,
534 struct snd_pcm_hw_params *hw_params)
535{
536 struct snd_pcm_runtime *runtime = substream->runtime;
537 struct fsl_dma_private *dma_private = runtime->private_data;
538 struct device *dev = component->dev;
539
540
541 unsigned int sample_bits =
542 snd_pcm_format_physical_width(params_format(hw_params));
543
544
545 unsigned int sample_bytes = sample_bits / 8;
546
547
548 dma_addr_t ssi_sxx_phys = dma_private->ssi_sxx_phys;
549
550
551 size_t buffer_size = params_buffer_bytes(hw_params);
552
553
554 size_t period_size = params_period_bytes(hw_params);
555
556
557 dma_addr_t temp_addr = substream->dma_buffer.addr;
558
559
560 struct ccsr_dma_channel __iomem *dma_channel = dma_private->dma_channel;
561
562 u32 mr;
563
564 unsigned int i;
565
566
567 dma_private->period_size = period_size;
568 dma_private->num_periods = params_periods(hw_params);
569 dma_private->dma_buf_end = dma_private->dma_buf_phys + buffer_size;
570 dma_private->dma_buf_next = dma_private->dma_buf_phys +
571 (NUM_DMA_LINKS * period_size);
572
573 if (dma_private->dma_buf_next >= dma_private->dma_buf_end)
574
575 dma_private->dma_buf_next = dma_private->dma_buf_phys;
576
577 mr = in_be32(&dma_channel->mr) & ~(CCSR_DMA_MR_BWC_MASK |
578 CCSR_DMA_MR_SAHTS_MASK | CCSR_DMA_MR_DAHTS_MASK);
579
580
581
582
583
584
585 switch (sample_bits) {
586 case 8:
587 mr |= CCSR_DMA_MR_DAHTS_1 | CCSR_DMA_MR_SAHTS_1;
588 ssi_sxx_phys += 3;
589 break;
590 case 16:
591 mr |= CCSR_DMA_MR_DAHTS_2 | CCSR_DMA_MR_SAHTS_2;
592 ssi_sxx_phys += 2;
593 break;
594 case 32:
595 mr |= CCSR_DMA_MR_DAHTS_4 | CCSR_DMA_MR_SAHTS_4;
596 break;
597 default:
598
599 dev_err(dev, "unsupported sample size %u\n", sample_bits);
600 return -EINVAL;
601 }
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634 mr |= CCSR_DMA_MR_BWC((dma_private->ssi_fifo_depth - 2) * sample_bytes);
635
636 out_be32(&dma_channel->mr, mr);
637
638 for (i = 0; i < NUM_DMA_LINKS; i++) {
639 struct fsl_dma_link_descriptor *link = &dma_private->link[i];
640
641 link->count = cpu_to_be32(period_size);
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
661 link->source_addr = cpu_to_be32(temp_addr);
662 link->source_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP |
663 upper_32_bits(temp_addr));
664
665 link->dest_addr = cpu_to_be32(ssi_sxx_phys);
666 link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_NOSNOOP |
667 upper_32_bits(ssi_sxx_phys));
668 } else {
669 link->source_addr = cpu_to_be32(ssi_sxx_phys);
670 link->source_attr = cpu_to_be32(CCSR_DMA_ATR_NOSNOOP |
671 upper_32_bits(ssi_sxx_phys));
672
673 link->dest_addr = cpu_to_be32(temp_addr);
674 link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP |
675 upper_32_bits(temp_addr));
676 }
677
678 temp_addr += period_size;
679 }
680
681 return 0;
682}
683
684
685
686
687
688
689
690
691
692
693
694
695
696static snd_pcm_uframes_t fsl_dma_pointer(struct snd_soc_component *component,
697 struct snd_pcm_substream *substream)
698{
699 struct snd_pcm_runtime *runtime = substream->runtime;
700 struct fsl_dma_private *dma_private = runtime->private_data;
701 struct device *dev = component->dev;
702 struct ccsr_dma_channel __iomem *dma_channel = dma_private->dma_channel;
703 dma_addr_t position;
704 snd_pcm_uframes_t frames;
705
706
707
708
709
710 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
711 position = in_be32(&dma_channel->sar);
712#ifdef CONFIG_PHYS_64BIT
713 position |= (u64)(in_be32(&dma_channel->satr) &
714 CCSR_DMA_ATR_ESAD_MASK) << 32;
715#endif
716 } else {
717 position = in_be32(&dma_channel->dar);
718#ifdef CONFIG_PHYS_64BIT
719 position |= (u64)(in_be32(&dma_channel->datr) &
720 CCSR_DMA_ATR_ESAD_MASK) << 32;
721#endif
722 }
723
724
725
726
727
728
729
730
731 if (!position)
732 return 0;
733
734 if ((position < dma_private->dma_buf_phys) ||
735 (position > dma_private->dma_buf_end)) {
736 dev_err(dev, "dma pointer is out of range, halting stream\n");
737 return SNDRV_PCM_POS_XRUN;
738 }
739
740 frames = bytes_to_frames(runtime, position - dma_private->dma_buf_phys);
741
742
743
744
745
746 if (frames == runtime->buffer_size)
747 frames = 0;
748
749 return frames;
750}
751
752
753
754
755
756
757
758
759
760static int fsl_dma_hw_free(struct snd_soc_component *component,
761 struct snd_pcm_substream *substream)
762{
763 struct snd_pcm_runtime *runtime = substream->runtime;
764 struct fsl_dma_private *dma_private = runtime->private_data;
765
766 if (dma_private) {
767 struct ccsr_dma_channel __iomem *dma_channel;
768
769 dma_channel = dma_private->dma_channel;
770
771
772 out_be32(&dma_channel->mr, CCSR_DMA_MR_CA);
773 out_be32(&dma_channel->mr, 0);
774
775
776 out_be32(&dma_channel->sr, -1);
777 out_be32(&dma_channel->clndar, 0);
778 out_be32(&dma_channel->eclndar, 0);
779 out_be32(&dma_channel->satr, 0);
780 out_be32(&dma_channel->sar, 0);
781 out_be32(&dma_channel->datr, 0);
782 out_be32(&dma_channel->dar, 0);
783 out_be32(&dma_channel->bcr, 0);
784 out_be32(&dma_channel->nlndar, 0);
785 out_be32(&dma_channel->enlndar, 0);
786 }
787
788 return 0;
789}
790
791
792
793
794static int fsl_dma_close(struct snd_soc_component *component,
795 struct snd_pcm_substream *substream)
796{
797 struct snd_pcm_runtime *runtime = substream->runtime;
798 struct fsl_dma_private *dma_private = runtime->private_data;
799 struct device *dev = component->dev;
800 struct dma_object *dma =
801 container_of(component->driver, struct dma_object, dai);
802
803 if (dma_private) {
804 if (dma_private->irq)
805 free_irq(dma_private->irq, dma_private);
806
807
808 dma_free_coherent(dev, sizeof(struct fsl_dma_private),
809 dma_private, dma_private->ld_buf_phys);
810 substream->runtime->private_data = NULL;
811 }
812
813 dma->assigned = false;
814
815 return 0;
816}
817
818
819
820
821static void fsl_dma_free_dma_buffers(struct snd_soc_component *component,
822 struct snd_pcm *pcm)
823{
824 struct snd_pcm_substream *substream;
825 unsigned int i;
826
827 for (i = 0; i < ARRAY_SIZE(pcm->streams); i++) {
828 substream = pcm->streams[i].substream;
829 if (substream) {
830 snd_dma_free_pages(&substream->dma_buffer);
831 substream->dma_buffer.area = NULL;
832 substream->dma_buffer.addr = 0;
833 }
834 }
835}
836
837
838
839
840
841
842
843
844
845
846
847
848static struct device_node *find_ssi_node(struct device_node *dma_channel_np)
849{
850 struct device_node *ssi_np, *np;
851
852 for_each_compatible_node(ssi_np, NULL, "fsl,mpc8610-ssi") {
853
854
855
856 np = of_parse_phandle(ssi_np, "fsl,playback-dma", 0);
857 of_node_put(np);
858 if (np == dma_channel_np)
859 return ssi_np;
860
861 np = of_parse_phandle(ssi_np, "fsl,capture-dma", 0);
862 of_node_put(np);
863 if (np == dma_channel_np)
864 return ssi_np;
865 }
866
867 return NULL;
868}
869
870static int fsl_soc_dma_probe(struct platform_device *pdev)
871{
872 struct dma_object *dma;
873 struct device_node *np = pdev->dev.of_node;
874 struct device_node *ssi_np;
875 struct resource res;
876 const uint32_t *iprop;
877 int ret;
878
879
880 ssi_np = find_ssi_node(np);
881 if (!ssi_np) {
882 dev_err(&pdev->dev, "cannot find parent SSI node\n");
883 return -ENODEV;
884 }
885
886 ret = of_address_to_resource(ssi_np, 0, &res);
887 if (ret) {
888 dev_err(&pdev->dev, "could not determine resources for %pOF\n",
889 ssi_np);
890 of_node_put(ssi_np);
891 return ret;
892 }
893
894 dma = kzalloc(sizeof(*dma), GFP_KERNEL);
895 if (!dma) {
896 of_node_put(ssi_np);
897 return -ENOMEM;
898 }
899
900 dma->dai.name = DRV_NAME;
901 dma->dai.open = fsl_dma_open;
902 dma->dai.close = fsl_dma_close;
903 dma->dai.hw_params = fsl_dma_hw_params;
904 dma->dai.hw_free = fsl_dma_hw_free;
905 dma->dai.pointer = fsl_dma_pointer;
906 dma->dai.pcm_construct = fsl_dma_new;
907 dma->dai.pcm_destruct = fsl_dma_free_dma_buffers;
908
909
910 dma->ssi_stx_phys = res.start + REG_SSI_STX0;
911 dma->ssi_srx_phys = res.start + REG_SSI_SRX0;
912
913 iprop = of_get_property(ssi_np, "fsl,fifo-depth", NULL);
914 if (iprop)
915 dma->ssi_fifo_depth = be32_to_cpup(iprop);
916 else
917
918 dma->ssi_fifo_depth = 8;
919
920 of_node_put(ssi_np);
921
922 ret = devm_snd_soc_register_component(&pdev->dev, &dma->dai, NULL, 0);
923 if (ret) {
924 dev_err(&pdev->dev, "could not register platform\n");
925 kfree(dma);
926 return ret;
927 }
928
929 dma->channel = of_iomap(np, 0);
930 dma->irq = irq_of_parse_and_map(np, 0);
931
932 dev_set_drvdata(&pdev->dev, dma);
933
934 return 0;
935}
936
937static int fsl_soc_dma_remove(struct platform_device *pdev)
938{
939 struct dma_object *dma = dev_get_drvdata(&pdev->dev);
940
941 iounmap(dma->channel);
942 irq_dispose_mapping(dma->irq);
943 kfree(dma);
944
945 return 0;
946}
947
948static const struct of_device_id fsl_soc_dma_ids[] = {
949 { .compatible = "fsl,ssi-dma-channel", },
950 {}
951};
952MODULE_DEVICE_TABLE(of, fsl_soc_dma_ids);
953
954static struct platform_driver fsl_soc_dma_driver = {
955 .driver = {
956 .name = "fsl-pcm-audio",
957 .of_match_table = fsl_soc_dma_ids,
958 },
959 .probe = fsl_soc_dma_probe,
960 .remove = fsl_soc_dma_remove,
961};
962
963module_platform_driver(fsl_soc_dma_driver);
964
965MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
966MODULE_DESCRIPTION("Freescale Elo DMA ASoC PCM Driver");
967MODULE_LICENSE("GPL v2");
968