]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blob - sound/soc/fsl/fsl_sai.c
Merge tag 'pm+acpi-3.15-rc1-3' of git://git.kernel.org/pub/scm/linux/kernel/git/rafae...
[mirror_ubuntu-hirsute-kernel.git] / sound / soc / fsl / fsl_sai.c
1 /*
2 * Freescale ALSA SoC Digital Audio Interface (SAI) driver.
3 *
4 * Copyright 2012-2013 Freescale Semiconductor, Inc.
5 *
6 * This program is free software, you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 2 of the License, or(at your
9 * option) any later version.
10 *
11 */
12
13 #include <linux/clk.h>
14 #include <linux/delay.h>
15 #include <linux/dmaengine.h>
16 #include <linux/module.h>
17 #include <linux/of_address.h>
18 #include <linux/regmap.h>
19 #include <linux/slab.h>
20 #include <sound/core.h>
21 #include <sound/dmaengine_pcm.h>
22 #include <sound/pcm_params.h>
23
24 #include "fsl_sai.h"
25
26 #define FSL_SAI_FLAGS (FSL_SAI_CSR_SEIE |\
27 FSL_SAI_CSR_FEIE)
28
29 static irqreturn_t fsl_sai_isr(int irq, void *devid)
30 {
31 struct fsl_sai *sai = (struct fsl_sai *)devid;
32 struct device *dev = &sai->pdev->dev;
33 u32 xcsr, mask;
34
35 /* Only handle those what we enabled */
36 mask = (FSL_SAI_FLAGS >> FSL_SAI_CSR_xIE_SHIFT) << FSL_SAI_CSR_xF_SHIFT;
37
38 /* Tx IRQ */
39 regmap_read(sai->regmap, FSL_SAI_TCSR, &xcsr);
40 xcsr &= mask;
41
42 if (xcsr & FSL_SAI_CSR_WSF)
43 dev_dbg(dev, "isr: Start of Tx word detected\n");
44
45 if (xcsr & FSL_SAI_CSR_SEF)
46 dev_warn(dev, "isr: Tx Frame sync error detected\n");
47
48 if (xcsr & FSL_SAI_CSR_FEF) {
49 dev_warn(dev, "isr: Transmit underrun detected\n");
50 /* FIFO reset for safety */
51 xcsr |= FSL_SAI_CSR_FR;
52 }
53
54 if (xcsr & FSL_SAI_CSR_FWF)
55 dev_dbg(dev, "isr: Enabled transmit FIFO is empty\n");
56
57 if (xcsr & FSL_SAI_CSR_FRF)
58 dev_dbg(dev, "isr: Transmit FIFO watermark has been reached\n");
59
60 regmap_update_bits(sai->regmap, FSL_SAI_TCSR,
61 FSL_SAI_CSR_xF_W_MASK | FSL_SAI_CSR_FR, xcsr);
62
63 /* Rx IRQ */
64 regmap_read(sai->regmap, FSL_SAI_RCSR, &xcsr);
65 xcsr &= mask;
66
67 if (xcsr & FSL_SAI_CSR_WSF)
68 dev_dbg(dev, "isr: Start of Rx word detected\n");
69
70 if (xcsr & FSL_SAI_CSR_SEF)
71 dev_warn(dev, "isr: Rx Frame sync error detected\n");
72
73 if (xcsr & FSL_SAI_CSR_FEF) {
74 dev_warn(dev, "isr: Receive overflow detected\n");
75 /* FIFO reset for safety */
76 xcsr |= FSL_SAI_CSR_FR;
77 }
78
79 if (xcsr & FSL_SAI_CSR_FWF)
80 dev_dbg(dev, "isr: Enabled receive FIFO is full\n");
81
82 if (xcsr & FSL_SAI_CSR_FRF)
83 dev_dbg(dev, "isr: Receive FIFO watermark has been reached\n");
84
85 regmap_update_bits(sai->regmap, FSL_SAI_RCSR,
86 FSL_SAI_CSR_xF_W_MASK | FSL_SAI_CSR_FR, xcsr);
87
88 return IRQ_HANDLED;
89 }
90
91 static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai,
92 int clk_id, unsigned int freq, int fsl_dir)
93 {
94 struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
95 u32 val_cr2, reg_cr2;
96
97 if (fsl_dir == FSL_FMT_TRANSMITTER)
98 reg_cr2 = FSL_SAI_TCR2;
99 else
100 reg_cr2 = FSL_SAI_RCR2;
101
102 regmap_read(sai->regmap, reg_cr2, &val_cr2);
103
104 val_cr2 &= ~FSL_SAI_CR2_MSEL_MASK;
105
106 switch (clk_id) {
107 case FSL_SAI_CLK_BUS:
108 val_cr2 |= FSL_SAI_CR2_MSEL_BUS;
109 break;
110 case FSL_SAI_CLK_MAST1:
111 val_cr2 |= FSL_SAI_CR2_MSEL_MCLK1;
112 break;
113 case FSL_SAI_CLK_MAST2:
114 val_cr2 |= FSL_SAI_CR2_MSEL_MCLK2;
115 break;
116 case FSL_SAI_CLK_MAST3:
117 val_cr2 |= FSL_SAI_CR2_MSEL_MCLK3;
118 break;
119 default:
120 return -EINVAL;
121 }
122
123 regmap_write(sai->regmap, reg_cr2, val_cr2);
124
125 return 0;
126 }
127
128 static int fsl_sai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
129 int clk_id, unsigned int freq, int dir)
130 {
131 int ret;
132
133 if (dir == SND_SOC_CLOCK_IN)
134 return 0;
135
136 ret = fsl_sai_set_dai_sysclk_tr(cpu_dai, clk_id, freq,
137 FSL_FMT_TRANSMITTER);
138 if (ret) {
139 dev_err(cpu_dai->dev, "Cannot set tx sysclk: %d\n", ret);
140 return ret;
141 }
142
143 ret = fsl_sai_set_dai_sysclk_tr(cpu_dai, clk_id, freq,
144 FSL_FMT_RECEIVER);
145 if (ret)
146 dev_err(cpu_dai->dev, "Cannot set rx sysclk: %d\n", ret);
147
148 return ret;
149 }
150
151 static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai,
152 unsigned int fmt, int fsl_dir)
153 {
154 struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
155 u32 val_cr2, val_cr4, reg_cr2, reg_cr4;
156
157 if (fsl_dir == FSL_FMT_TRANSMITTER) {
158 reg_cr2 = FSL_SAI_TCR2;
159 reg_cr4 = FSL_SAI_TCR4;
160 } else {
161 reg_cr2 = FSL_SAI_RCR2;
162 reg_cr4 = FSL_SAI_RCR4;
163 }
164
165 regmap_read(sai->regmap, reg_cr2, &val_cr2);
166 regmap_read(sai->regmap, reg_cr4, &val_cr4);
167
168 if (sai->big_endian_data)
169 val_cr4 &= ~FSL_SAI_CR4_MF;
170 else
171 val_cr4 |= FSL_SAI_CR4_MF;
172
173 /* DAI mode */
174 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
175 case SND_SOC_DAIFMT_I2S:
176 /*
177 * Frame low, 1clk before data, one word length for frame sync,
178 * frame sync starts one serial clock cycle earlier,
179 * that is, together with the last bit of the previous
180 * data word.
181 */
182 val_cr2 |= FSL_SAI_CR2_BCP;
183 val_cr4 |= FSL_SAI_CR4_FSE | FSL_SAI_CR4_FSP;
184 break;
185 case SND_SOC_DAIFMT_LEFT_J:
186 /*
187 * Frame high, one word length for frame sync,
188 * frame sync asserts with the first bit of the frame.
189 */
190 val_cr2 |= FSL_SAI_CR2_BCP;
191 val_cr4 &= ~(FSL_SAI_CR4_FSE | FSL_SAI_CR4_FSP);
192 break;
193 case SND_SOC_DAIFMT_DSP_A:
194 /*
195 * Frame high, 1clk before data, one bit for frame sync,
196 * frame sync starts one serial clock cycle earlier,
197 * that is, together with the last bit of the previous
198 * data word.
199 */
200 val_cr2 |= FSL_SAI_CR2_BCP;
201 val_cr4 &= ~FSL_SAI_CR4_FSP;
202 val_cr4 |= FSL_SAI_CR4_FSE;
203 sai->is_dsp_mode = true;
204 break;
205 case SND_SOC_DAIFMT_DSP_B:
206 /*
207 * Frame high, one bit for frame sync,
208 * frame sync asserts with the first bit of the frame.
209 */
210 val_cr2 |= FSL_SAI_CR2_BCP;
211 val_cr4 &= ~(FSL_SAI_CR4_FSE | FSL_SAI_CR4_FSP);
212 sai->is_dsp_mode = true;
213 break;
214 case SND_SOC_DAIFMT_RIGHT_J:
215 /* To be done */
216 default:
217 return -EINVAL;
218 }
219
220 /* DAI clock inversion */
221 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
222 case SND_SOC_DAIFMT_IB_IF:
223 /* Invert both clocks */
224 val_cr2 ^= FSL_SAI_CR2_BCP;
225 val_cr4 ^= FSL_SAI_CR4_FSP;
226 break;
227 case SND_SOC_DAIFMT_IB_NF:
228 /* Invert bit clock */
229 val_cr2 ^= FSL_SAI_CR2_BCP;
230 break;
231 case SND_SOC_DAIFMT_NB_IF:
232 /* Invert frame clock */
233 val_cr4 ^= FSL_SAI_CR4_FSP;
234 break;
235 case SND_SOC_DAIFMT_NB_NF:
236 /* Nothing to do for both normal cases */
237 break;
238 default:
239 return -EINVAL;
240 }
241
242 /* DAI clock master masks */
243 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
244 case SND_SOC_DAIFMT_CBS_CFS:
245 val_cr2 |= FSL_SAI_CR2_BCD_MSTR;
246 val_cr4 |= FSL_SAI_CR4_FSD_MSTR;
247 break;
248 case SND_SOC_DAIFMT_CBM_CFM:
249 val_cr2 &= ~FSL_SAI_CR2_BCD_MSTR;
250 val_cr4 &= ~FSL_SAI_CR4_FSD_MSTR;
251 break;
252 case SND_SOC_DAIFMT_CBS_CFM:
253 val_cr2 |= FSL_SAI_CR2_BCD_MSTR;
254 val_cr4 &= ~FSL_SAI_CR4_FSD_MSTR;
255 break;
256 case SND_SOC_DAIFMT_CBM_CFS:
257 val_cr2 &= ~FSL_SAI_CR2_BCD_MSTR;
258 val_cr4 |= FSL_SAI_CR4_FSD_MSTR;
259 break;
260 default:
261 return -EINVAL;
262 }
263
264 regmap_write(sai->regmap, reg_cr2, val_cr2);
265 regmap_write(sai->regmap, reg_cr4, val_cr4);
266
267 return 0;
268 }
269
270 static int fsl_sai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
271 {
272 int ret;
273
274 ret = fsl_sai_set_dai_fmt_tr(cpu_dai, fmt, FSL_FMT_TRANSMITTER);
275 if (ret) {
276 dev_err(cpu_dai->dev, "Cannot set tx format: %d\n", ret);
277 return ret;
278 }
279
280 ret = fsl_sai_set_dai_fmt_tr(cpu_dai, fmt, FSL_FMT_RECEIVER);
281 if (ret)
282 dev_err(cpu_dai->dev, "Cannot set rx format: %d\n", ret);
283
284 return ret;
285 }
286
287 static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
288 struct snd_pcm_hw_params *params,
289 struct snd_soc_dai *cpu_dai)
290 {
291 struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
292 u32 val_cr4, val_cr5, val_mr, reg_cr4, reg_cr5, reg_mr;
293 unsigned int channels = params_channels(params);
294 u32 word_width = snd_pcm_format_width(params_format(params));
295
296 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
297 reg_cr4 = FSL_SAI_TCR4;
298 reg_cr5 = FSL_SAI_TCR5;
299 reg_mr = FSL_SAI_TMR;
300 } else {
301 reg_cr4 = FSL_SAI_RCR4;
302 reg_cr5 = FSL_SAI_RCR5;
303 reg_mr = FSL_SAI_RMR;
304 }
305
306 regmap_read(sai->regmap, reg_cr4, &val_cr4);
307 regmap_read(sai->regmap, reg_cr4, &val_cr5);
308
309 val_cr4 &= ~FSL_SAI_CR4_SYWD_MASK;
310 val_cr4 &= ~FSL_SAI_CR4_FRSZ_MASK;
311
312 val_cr5 &= ~FSL_SAI_CR5_WNW_MASK;
313 val_cr5 &= ~FSL_SAI_CR5_W0W_MASK;
314 val_cr5 &= ~FSL_SAI_CR5_FBT_MASK;
315
316 if (!sai->is_dsp_mode)
317 val_cr4 |= FSL_SAI_CR4_SYWD(word_width);
318
319 val_cr5 |= FSL_SAI_CR5_WNW(word_width);
320 val_cr5 |= FSL_SAI_CR5_W0W(word_width);
321
322 val_cr5 &= ~FSL_SAI_CR5_FBT_MASK;
323 if (sai->big_endian_data)
324 val_cr5 |= FSL_SAI_CR5_FBT(0);
325 else
326 val_cr5 |= FSL_SAI_CR5_FBT(word_width - 1);
327
328 val_cr4 |= FSL_SAI_CR4_FRSZ(channels);
329 val_mr = ~0UL - ((1 << channels) - 1);
330
331 regmap_write(sai->regmap, reg_cr4, val_cr4);
332 regmap_write(sai->regmap, reg_cr5, val_cr5);
333 regmap_write(sai->regmap, reg_mr, val_mr);
334
335 return 0;
336 }
337
338 static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
339 struct snd_soc_dai *cpu_dai)
340 {
341 struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
342 u32 tcsr, rcsr;
343
344 /*
345 * The transmitter bit clock and frame sync are to be
346 * used by both the transmitter and receiver.
347 */
348 regmap_update_bits(sai->regmap, FSL_SAI_TCR2, FSL_SAI_CR2_SYNC,
349 ~FSL_SAI_CR2_SYNC);
350 regmap_update_bits(sai->regmap, FSL_SAI_RCR2, FSL_SAI_CR2_SYNC,
351 FSL_SAI_CR2_SYNC);
352
353 regmap_read(sai->regmap, FSL_SAI_TCSR, &tcsr);
354 regmap_read(sai->regmap, FSL_SAI_RCSR, &rcsr);
355
356 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
357 tcsr |= FSL_SAI_CSR_FRDE;
358 rcsr &= ~FSL_SAI_CSR_FRDE;
359 } else {
360 rcsr |= FSL_SAI_CSR_FRDE;
361 tcsr &= ~FSL_SAI_CSR_FRDE;
362 }
363
364 /*
365 * It is recommended that the transmitter is the last enabled
366 * and the first disabled.
367 */
368 switch (cmd) {
369 case SNDRV_PCM_TRIGGER_START:
370 case SNDRV_PCM_TRIGGER_RESUME:
371 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
372 tcsr |= FSL_SAI_CSR_TERE;
373 rcsr |= FSL_SAI_CSR_TERE;
374
375 regmap_write(sai->regmap, FSL_SAI_RCSR, rcsr);
376 regmap_write(sai->regmap, FSL_SAI_TCSR, tcsr);
377 break;
378 case SNDRV_PCM_TRIGGER_STOP:
379 case SNDRV_PCM_TRIGGER_SUSPEND:
380 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
381 if (!(cpu_dai->playback_active || cpu_dai->capture_active)) {
382 tcsr &= ~FSL_SAI_CSR_TERE;
383 rcsr &= ~FSL_SAI_CSR_TERE;
384 }
385
386 regmap_write(sai->regmap, FSL_SAI_TCSR, tcsr);
387 regmap_write(sai->regmap, FSL_SAI_RCSR, rcsr);
388 break;
389 default:
390 return -EINVAL;
391 }
392
393 return 0;
394 }
395
396 static int fsl_sai_startup(struct snd_pcm_substream *substream,
397 struct snd_soc_dai *cpu_dai)
398 {
399 struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
400 u32 reg;
401
402 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
403 reg = FSL_SAI_TCR3;
404 else
405 reg = FSL_SAI_RCR3;
406
407 regmap_update_bits(sai->regmap, reg, FSL_SAI_CR3_TRCE,
408 FSL_SAI_CR3_TRCE);
409
410 return 0;
411 }
412
413 static void fsl_sai_shutdown(struct snd_pcm_substream *substream,
414 struct snd_soc_dai *cpu_dai)
415 {
416 struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
417 u32 reg;
418
419 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
420 reg = FSL_SAI_TCR3;
421 else
422 reg = FSL_SAI_RCR3;
423
424 regmap_update_bits(sai->regmap, reg, FSL_SAI_CR3_TRCE,
425 ~FSL_SAI_CR3_TRCE);
426 }
427
428 static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = {
429 .set_sysclk = fsl_sai_set_dai_sysclk,
430 .set_fmt = fsl_sai_set_dai_fmt,
431 .hw_params = fsl_sai_hw_params,
432 .trigger = fsl_sai_trigger,
433 .startup = fsl_sai_startup,
434 .shutdown = fsl_sai_shutdown,
435 };
436
437 static int fsl_sai_dai_probe(struct snd_soc_dai *cpu_dai)
438 {
439 struct fsl_sai *sai = dev_get_drvdata(cpu_dai->dev);
440
441 regmap_update_bits(sai->regmap, FSL_SAI_TCSR, 0xffffffff, FSL_SAI_FLAGS);
442 regmap_update_bits(sai->regmap, FSL_SAI_RCSR, 0xffffffff, FSL_SAI_FLAGS);
443 regmap_update_bits(sai->regmap, FSL_SAI_TCR1, FSL_SAI_CR1_RFW_MASK,
444 FSL_SAI_MAXBURST_TX * 2);
445 regmap_update_bits(sai->regmap, FSL_SAI_RCR1, FSL_SAI_CR1_RFW_MASK,
446 FSL_SAI_MAXBURST_RX - 1);
447
448 snd_soc_dai_init_dma_data(cpu_dai, &sai->dma_params_tx,
449 &sai->dma_params_rx);
450
451 snd_soc_dai_set_drvdata(cpu_dai, sai);
452
453 return 0;
454 }
455
456 static struct snd_soc_dai_driver fsl_sai_dai = {
457 .probe = fsl_sai_dai_probe,
458 .playback = {
459 .channels_min = 1,
460 .channels_max = 2,
461 .rates = SNDRV_PCM_RATE_8000_96000,
462 .formats = FSL_SAI_FORMATS,
463 },
464 .capture = {
465 .channels_min = 1,
466 .channels_max = 2,
467 .rates = SNDRV_PCM_RATE_8000_96000,
468 .formats = FSL_SAI_FORMATS,
469 },
470 .ops = &fsl_sai_pcm_dai_ops,
471 };
472
473 static const struct snd_soc_component_driver fsl_component = {
474 .name = "fsl-sai",
475 };
476
477 static bool fsl_sai_readable_reg(struct device *dev, unsigned int reg)
478 {
479 switch (reg) {
480 case FSL_SAI_TCSR:
481 case FSL_SAI_TCR1:
482 case FSL_SAI_TCR2:
483 case FSL_SAI_TCR3:
484 case FSL_SAI_TCR4:
485 case FSL_SAI_TCR5:
486 case FSL_SAI_TFR:
487 case FSL_SAI_TMR:
488 case FSL_SAI_RCSR:
489 case FSL_SAI_RCR1:
490 case FSL_SAI_RCR2:
491 case FSL_SAI_RCR3:
492 case FSL_SAI_RCR4:
493 case FSL_SAI_RCR5:
494 case FSL_SAI_RDR:
495 case FSL_SAI_RFR:
496 case FSL_SAI_RMR:
497 return true;
498 default:
499 return false;
500 }
501 }
502
503 static bool fsl_sai_volatile_reg(struct device *dev, unsigned int reg)
504 {
505 switch (reg) {
506 case FSL_SAI_TFR:
507 case FSL_SAI_RFR:
508 case FSL_SAI_TDR:
509 case FSL_SAI_RDR:
510 return true;
511 default:
512 return false;
513 }
514
515 }
516
517 static bool fsl_sai_writeable_reg(struct device *dev, unsigned int reg)
518 {
519 switch (reg) {
520 case FSL_SAI_TCSR:
521 case FSL_SAI_TCR1:
522 case FSL_SAI_TCR2:
523 case FSL_SAI_TCR3:
524 case FSL_SAI_TCR4:
525 case FSL_SAI_TCR5:
526 case FSL_SAI_TDR:
527 case FSL_SAI_TMR:
528 case FSL_SAI_RCSR:
529 case FSL_SAI_RCR1:
530 case FSL_SAI_RCR2:
531 case FSL_SAI_RCR3:
532 case FSL_SAI_RCR4:
533 case FSL_SAI_RCR5:
534 case FSL_SAI_RMR:
535 return true;
536 default:
537 return false;
538 }
539 }
540
541 static struct regmap_config fsl_sai_regmap_config = {
542 .reg_bits = 32,
543 .reg_stride = 4,
544 .val_bits = 32,
545
546 .max_register = FSL_SAI_RMR,
547 .readable_reg = fsl_sai_readable_reg,
548 .volatile_reg = fsl_sai_volatile_reg,
549 .writeable_reg = fsl_sai_writeable_reg,
550 };
551
552 static int fsl_sai_probe(struct platform_device *pdev)
553 {
554 struct device_node *np = pdev->dev.of_node;
555 struct fsl_sai *sai;
556 struct resource *res;
557 void __iomem *base;
558 int irq, ret;
559
560 sai = devm_kzalloc(&pdev->dev, sizeof(*sai), GFP_KERNEL);
561 if (!sai)
562 return -ENOMEM;
563
564 sai->pdev = pdev;
565
566 sai->big_endian_regs = of_property_read_bool(np, "big-endian-regs");
567 if (sai->big_endian_regs)
568 fsl_sai_regmap_config.val_format_endian = REGMAP_ENDIAN_BIG;
569
570 sai->big_endian_data = of_property_read_bool(np, "big-endian-data");
571
572 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
573 base = devm_ioremap_resource(&pdev->dev, res);
574 if (IS_ERR(base))
575 return PTR_ERR(base);
576
577 sai->regmap = devm_regmap_init_mmio_clk(&pdev->dev,
578 "sai", base, &fsl_sai_regmap_config);
579 if (IS_ERR(sai->regmap)) {
580 dev_err(&pdev->dev, "regmap init failed\n");
581 return PTR_ERR(sai->regmap);
582 }
583
584 irq = platform_get_irq(pdev, 0);
585 if (irq < 0) {
586 dev_err(&pdev->dev, "no irq for node %s\n", np->full_name);
587 return irq;
588 }
589
590 ret = devm_request_irq(&pdev->dev, irq, fsl_sai_isr, 0, np->name, sai);
591 if (ret) {
592 dev_err(&pdev->dev, "failed to claim irq %u\n", irq);
593 return ret;
594 }
595
596 sai->dma_params_rx.addr = res->start + FSL_SAI_RDR;
597 sai->dma_params_tx.addr = res->start + FSL_SAI_TDR;
598 sai->dma_params_rx.maxburst = FSL_SAI_MAXBURST_RX;
599 sai->dma_params_tx.maxburst = FSL_SAI_MAXBURST_TX;
600
601 platform_set_drvdata(pdev, sai);
602
603 ret = devm_snd_soc_register_component(&pdev->dev, &fsl_component,
604 &fsl_sai_dai, 1);
605 if (ret)
606 return ret;
607
608 return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL,
609 SND_DMAENGINE_PCM_FLAG_NO_RESIDUE);
610 }
611
612 static const struct of_device_id fsl_sai_ids[] = {
613 { .compatible = "fsl,vf610-sai", },
614 { /* sentinel */ }
615 };
616
617 static struct platform_driver fsl_sai_driver = {
618 .probe = fsl_sai_probe,
619 .driver = {
620 .name = "fsl-sai",
621 .owner = THIS_MODULE,
622 .of_match_table = fsl_sai_ids,
623 },
624 };
625 module_platform_driver(fsl_sai_driver);
626
627 MODULE_DESCRIPTION("Freescale Soc SAI Interface");
628 MODULE_AUTHOR("Xiubo Li, <Li.Xiubo@freescale.com>");
629 MODULE_ALIAS("platform:fsl-sai");
630 MODULE_LICENSE("GPL");