forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-09-20 cf4ce59b3b70238352c7f1729f0f7223214828ad
kernel/sound/soc/fsl/fsl_sai.c
....@@ -9,6 +9,8 @@
99 #include <linux/dmaengine.h>
1010 #include <linux/module.h>
1111 #include <linux/of_address.h>
12
+#include <linux/of_device.h>
13
+#include <linux/pm_runtime.h>
1214 #include <linux/regmap.h>
1315 #include <linux/slab.h>
1416 #include <linux/time.h>
....@@ -35,9 +37,28 @@
3537 .list = fsl_sai_rates,
3638 };
3739
40
+/**
41
+ * fsl_sai_dir_is_synced - Check if stream is synced by the opposite stream
42
+ *
43
+ * SAI supports synchronous mode using bit/frame clocks of either Transmitter's
44
+ * or Receiver's for both streams. This function is used to check if clocks of
45
+ * the stream's are synced by the opposite stream.
46
+ *
47
+ * @sai: SAI context
48
+ * @dir: stream direction
49
+ */
50
+static inline bool fsl_sai_dir_is_synced(struct fsl_sai *sai, int dir)
51
+{
52
+ int adir = (dir == TX) ? RX : TX;
53
+
54
+ /* current dir in async mode while opposite dir in sync mode */
55
+ return !sai->synchronous[dir] && sai->synchronous[adir];
56
+}
57
+
3858 static irqreturn_t fsl_sai_isr(int irq, void *devid)
3959 {
4060 struct fsl_sai *sai = (struct fsl_sai *)devid;
61
+ unsigned int ofs = sai->soc_data->reg_offset;
4162 struct device *dev = &sai->pdev->dev;
4263 u32 flags, xcsr, mask;
4364 bool irq_none = true;
....@@ -50,7 +71,7 @@
5071 mask = (FSL_SAI_FLAGS >> FSL_SAI_CSR_xIE_SHIFT) << FSL_SAI_CSR_xF_SHIFT;
5172
5273 /* Tx IRQ */
53
- regmap_read(sai->regmap, FSL_SAI_TCSR, &xcsr);
74
+ regmap_read(sai->regmap, FSL_SAI_TCSR(ofs), &xcsr);
5475 flags = xcsr & mask;
5576
5677 if (flags)
....@@ -62,10 +83,10 @@
6283 dev_dbg(dev, "isr: Start of Tx word detected\n");
6384
6485 if (flags & FSL_SAI_CSR_SEF)
65
- dev_warn(dev, "isr: Tx Frame sync error detected\n");
86
+ dev_dbg(dev, "isr: Tx Frame sync error detected\n");
6687
6788 if (flags & FSL_SAI_CSR_FEF) {
68
- dev_warn(dev, "isr: Transmit underrun detected\n");
89
+ dev_dbg(dev, "isr: Transmit underrun detected\n");
6990 /* FIFO reset for safety */
7091 xcsr |= FSL_SAI_CSR_FR;
7192 }
....@@ -80,11 +101,11 @@
80101 xcsr &= ~FSL_SAI_CSR_xF_MASK;
81102
82103 if (flags)
83
- regmap_write(sai->regmap, FSL_SAI_TCSR, flags | xcsr);
104
+ regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), flags | xcsr);
84105
85106 irq_rx:
86107 /* Rx IRQ */
87
- regmap_read(sai->regmap, FSL_SAI_RCSR, &xcsr);
108
+ regmap_read(sai->regmap, FSL_SAI_RCSR(ofs), &xcsr);
88109 flags = xcsr & mask;
89110
90111 if (flags)
....@@ -96,10 +117,10 @@
96117 dev_dbg(dev, "isr: Start of Rx word detected\n");
97118
98119 if (flags & FSL_SAI_CSR_SEF)
99
- dev_warn(dev, "isr: Rx Frame sync error detected\n");
120
+ dev_dbg(dev, "isr: Rx Frame sync error detected\n");
100121
101122 if (flags & FSL_SAI_CSR_FEF) {
102
- dev_warn(dev, "isr: Receive overflow detected\n");
123
+ dev_dbg(dev, "isr: Receive overflow detected\n");
103124 /* FIFO reset for safety */
104125 xcsr |= FSL_SAI_CSR_FR;
105126 }
....@@ -114,7 +135,7 @@
114135 xcsr &= ~FSL_SAI_CSR_xF_MASK;
115136
116137 if (flags)
117
- regmap_write(sai->regmap, FSL_SAI_RCSR, flags | xcsr);
138
+ regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), flags | xcsr);
118139
119140 out:
120141 if (irq_none)
....@@ -134,10 +155,21 @@
134155 return 0;
135156 }
136157
158
+static int fsl_sai_set_dai_bclk_ratio(struct snd_soc_dai *dai,
159
+ unsigned int ratio)
160
+{
161
+ struct fsl_sai *sai = snd_soc_dai_get_drvdata(dai);
162
+
163
+ sai->bclk_ratio = ratio;
164
+
165
+ return 0;
166
+}
167
+
137168 static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai,
138169 int clk_id, unsigned int freq, int fsl_dir)
139170 {
140171 struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
172
+ unsigned int ofs = sai->soc_data->reg_offset;
141173 bool tx = fsl_dir == FSL_FMT_TRANSMITTER;
142174 u32 val_cr2 = 0;
143175
....@@ -158,7 +190,7 @@
158190 return -EINVAL;
159191 }
160192
161
- regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx),
193
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx, ofs),
162194 FSL_SAI_CR2_MSEL_MASK, val_cr2);
163195
164196 return 0;
....@@ -191,12 +223,14 @@
191223 unsigned int fmt, int fsl_dir)
192224 {
193225 struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
226
+ unsigned int ofs = sai->soc_data->reg_offset;
194227 bool tx = fsl_dir == FSL_FMT_TRANSMITTER;
195228 u32 val_cr2 = 0, val_cr4 = 0;
196229
197230 if (!sai->is_lsb_first)
198231 val_cr4 |= FSL_SAI_CR4_MF;
199232
233
+ sai->is_dsp_mode = false;
200234 /* DAI mode */
201235 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
202236 case SND_SOC_DAIFMT_I2S:
....@@ -285,9 +319,9 @@
285319 return -EINVAL;
286320 }
287321
288
- regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx),
322
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx, ofs),
289323 FSL_SAI_CR2_BCP | FSL_SAI_CR2_BCD_MSTR, val_cr2);
290
- regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx),
324
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs),
291325 FSL_SAI_CR4_MF | FSL_SAI_CR4_FSE |
292326 FSL_SAI_CR4_FSP | FSL_SAI_CR4_FSD_MSTR, val_cr4);
293327
....@@ -314,8 +348,11 @@
314348 static int fsl_sai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq)
315349 {
316350 struct fsl_sai *sai = snd_soc_dai_get_drvdata(dai);
351
+ unsigned int ofs = sai->soc_data->reg_offset;
317352 unsigned long clk_rate;
318353 u32 savediv = 0, ratio, savesub = freq;
354
+ int adir = tx ? RX : TX;
355
+ int dir = tx ? TX : RX;
319356 u32 id;
320357 int ret = 0;
321358
....@@ -374,19 +411,17 @@
374411 * 4) For Tx and Rx are both Synchronous with another SAI, we just
375412 * ignore it.
376413 */
377
- if ((sai->synchronous[TX] && !sai->synchronous[RX]) ||
378
- (!tx && !sai->synchronous[RX])) {
379
- regmap_update_bits(sai->regmap, FSL_SAI_RCR2,
414
+ if (fsl_sai_dir_is_synced(sai, adir)) {
415
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR2(!tx, ofs),
380416 FSL_SAI_CR2_MSEL_MASK,
381417 FSL_SAI_CR2_MSEL(sai->mclk_id[tx]));
382
- regmap_update_bits(sai->regmap, FSL_SAI_RCR2,
418
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR2(!tx, ofs),
383419 FSL_SAI_CR2_DIV_MASK, savediv - 1);
384
- } else if ((sai->synchronous[RX] && !sai->synchronous[TX]) ||
385
- (tx && !sai->synchronous[TX])) {
386
- regmap_update_bits(sai->regmap, FSL_SAI_TCR2,
420
+ } else if (!sai->synchronous[dir]) {
421
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx, ofs),
387422 FSL_SAI_CR2_MSEL_MASK,
388423 FSL_SAI_CR2_MSEL(sai->mclk_id[tx]));
389
- regmap_update_bits(sai->regmap, FSL_SAI_TCR2,
424
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx, ofs),
390425 FSL_SAI_CR2_DIV_MASK, savediv - 1);
391426 }
392427
....@@ -401,12 +436,15 @@
401436 struct snd_soc_dai *cpu_dai)
402437 {
403438 struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
439
+ unsigned int ofs = sai->soc_data->reg_offset;
404440 bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
405441 unsigned int channels = params_channels(params);
406442 u32 word_width = params_width(params);
407443 u32 val_cr4 = 0, val_cr5 = 0;
408444 u32 slots = (channels == 1) ? 2 : channels;
409445 u32 slot_width = word_width;
446
+ int adir = tx ? RX : TX;
447
+ u32 pins;
410448 int ret;
411449
412450 if (sai->slots)
....@@ -415,9 +453,17 @@
415453 if (sai->slot_width)
416454 slot_width = sai->slot_width;
417455
456
+ pins = DIV_ROUND_UP(channels, slots);
457
+
418458 if (!sai->is_slave_mode) {
419
- ret = fsl_sai_set_bclk(cpu_dai, tx,
420
- slots * slot_width * params_rate(params));
459
+ if (sai->bclk_ratio)
460
+ ret = fsl_sai_set_bclk(cpu_dai, tx,
461
+ sai->bclk_ratio *
462
+ params_rate(params));
463
+ else
464
+ ret = fsl_sai_set_bclk(cpu_dai, tx,
465
+ slots * slot_width *
466
+ params_rate(params));
421467 if (ret)
422468 return ret;
423469
....@@ -444,42 +490,38 @@
444490
445491 val_cr4 |= FSL_SAI_CR4_FRSZ(slots);
446492
493
+ /* Set to output mode to avoid tri-stated data pins */
494
+ if (tx)
495
+ val_cr4 |= FSL_SAI_CR4_CHMOD;
496
+
447497 /*
448498 * For SAI master mode, when Tx(Rx) sync with Rx(Tx) clock, Rx(Tx) will
449499 * generate bclk and frame clock for Tx(Rx), we should set RCR4(TCR4),
450
- * RCR5(TCR5) and RMR(TMR) for playback(capture), or there will be sync
451
- * error.
500
+ * RCR5(TCR5) for playback(capture), or there will be sync error.
452501 */
453502
454
- if (!sai->is_slave_mode) {
455
- if (!sai->synchronous[TX] && sai->synchronous[RX] && !tx) {
456
- regmap_update_bits(sai->regmap, FSL_SAI_TCR4,
457
- FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK,
458
- val_cr4);
459
- regmap_update_bits(sai->regmap, FSL_SAI_TCR5,
460
- FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK |
461
- FSL_SAI_CR5_FBT_MASK, val_cr5);
462
- regmap_write(sai->regmap, FSL_SAI_TMR,
463
- ~0UL - ((1 << channels) - 1));
464
- } else if (!sai->synchronous[RX] && sai->synchronous[TX] && tx) {
465
- regmap_update_bits(sai->regmap, FSL_SAI_RCR4,
466
- FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK,
467
- val_cr4);
468
- regmap_update_bits(sai->regmap, FSL_SAI_RCR5,
469
- FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK |
470
- FSL_SAI_CR5_FBT_MASK, val_cr5);
471
- regmap_write(sai->regmap, FSL_SAI_RMR,
472
- ~0UL - ((1 << channels) - 1));
473
- }
503
+ if (!sai->is_slave_mode && fsl_sai_dir_is_synced(sai, adir)) {
504
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR4(!tx, ofs),
505
+ FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK |
506
+ FSL_SAI_CR4_CHMOD_MASK,
507
+ val_cr4);
508
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR5(!tx, ofs),
509
+ FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK |
510
+ FSL_SAI_CR5_FBT_MASK, val_cr5);
474511 }
475512
476
- regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx),
477
- FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK,
513
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx, ofs),
514
+ FSL_SAI_CR3_TRCE_MASK,
515
+ FSL_SAI_CR3_TRCE((1 << pins) - 1));
516
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs),
517
+ FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK |
518
+ FSL_SAI_CR4_CHMOD_MASK,
478519 val_cr4);
479
- regmap_update_bits(sai->regmap, FSL_SAI_xCR5(tx),
520
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR5(tx, ofs),
480521 FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK |
481522 FSL_SAI_CR5_FBT_MASK, val_cr5);
482
- regmap_write(sai->regmap, FSL_SAI_xMR(tx), ~0UL - ((1 << channels) - 1));
523
+ regmap_write(sai->regmap, FSL_SAI_xMR(tx),
524
+ ~0UL - ((1 << min(channels, slots)) - 1));
483525
484526 return 0;
485527 }
....@@ -489,6 +531,10 @@
489531 {
490532 struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
491533 bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
534
+ unsigned int ofs = sai->soc_data->reg_offset;
535
+
536
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx, ofs),
537
+ FSL_SAI_CR3_TRCE_MASK, 0);
492538
493539 if (!sai->is_slave_mode &&
494540 sai->mclk_streams & BIT(substream->stream)) {
....@@ -499,22 +545,58 @@
499545 return 0;
500546 }
501547
548
+static void fsl_sai_config_disable(struct fsl_sai *sai, int dir)
549
+{
550
+ unsigned int ofs = sai->soc_data->reg_offset;
551
+ bool tx = dir == TX;
552
+ u32 xcsr, count = 100;
553
+
554
+ regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
555
+ FSL_SAI_CSR_TERE | FSL_SAI_CSR_BCE, 0);
556
+
557
+ /* TERE will remain set till the end of current frame */
558
+ do {
559
+ udelay(10);
560
+ regmap_read(sai->regmap, FSL_SAI_xCSR(tx, ofs), &xcsr);
561
+ } while (--count && xcsr & FSL_SAI_CSR_TERE);
562
+
563
+ regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
564
+ FSL_SAI_CSR_FR, FSL_SAI_CSR_FR);
565
+
566
+ /*
567
+ * For sai master mode, after several open/close sai,
568
+ * there will be no frame clock, and can't recover
569
+ * anymore. Add software reset to fix this issue.
570
+ * This is a hardware bug, and will be fix in the
571
+ * next sai version.
572
+ */
573
+ if (!sai->is_slave_mode) {
574
+ /* Software Reset */
575
+ regmap_write(sai->regmap, FSL_SAI_xCSR(tx, ofs), FSL_SAI_CSR_SR);
576
+ /* Clear SR bit to finish the reset */
577
+ regmap_write(sai->regmap, FSL_SAI_xCSR(tx, ofs), 0);
578
+ }
579
+}
502580
503581 static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
504582 struct snd_soc_dai *cpu_dai)
505583 {
506584 struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
585
+ unsigned int ofs = sai->soc_data->reg_offset;
586
+
507587 bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
508
- u32 xcsr, count = 100;
588
+ int adir = tx ? RX : TX;
589
+ int dir = tx ? TX : RX;
590
+ u32 xcsr;
509591
510592 /*
511593 * Asynchronous mode: Clear SYNC for both Tx and Rx.
512594 * Rx sync with Tx clocks: Clear SYNC for Tx, set it for Rx.
513595 * Tx sync with Rx clocks: Clear SYNC for Rx, set it for Tx.
514596 */
515
- regmap_update_bits(sai->regmap, FSL_SAI_TCR2, FSL_SAI_CR2_SYNC,
516
- sai->synchronous[TX] ? FSL_SAI_CR2_SYNC : 0);
517
- regmap_update_bits(sai->regmap, FSL_SAI_RCR2, FSL_SAI_CR2_SYNC,
597
+ regmap_update_bits(sai->regmap, FSL_SAI_TCR2(ofs), FSL_SAI_CR2_SYNC,
598
+ sai->synchronous[TX] ? FSL_SAI_CR2_SYNC : 0);
599
+ regmap_update_bits(sai->regmap, FSL_SAI_RCR2(ofs), FSL_SAI_CR2_SYNC,
518600 sai->synchronous[RX] ? FSL_SAI_CR2_SYNC : 0);
519601
520602 /*
....@@ -525,63 +607,56 @@
525607 case SNDRV_PCM_TRIGGER_START:
526608 case SNDRV_PCM_TRIGGER_RESUME:
527609 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
528
- regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx),
610
+ regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
529611 FSL_SAI_CSR_FRDE, FSL_SAI_CSR_FRDE);
530612
531
- regmap_update_bits(sai->regmap, FSL_SAI_RCSR,
613
+ regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
532614 FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE);
533
- regmap_update_bits(sai->regmap, FSL_SAI_TCSR,
534
- FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE);
615
+ /*
616
+ * Enable the opposite direction for synchronous mode
617
+ * 1. Tx sync with Rx: only set RE for Rx; set TE & RE for Tx
618
+ * 2. Rx sync with Tx: only set TE for Tx; set RE & TE for Rx
619
+ *
620
+ * RM recommends to enable RE after TE for case 1 and to enable
621
+ * TE after RE for case 2, but we here may not always guarantee
622
+ * that happens: "arecord 1.wav; aplay 2.wav" in case 1 enables
623
+ * TE after RE, which is against what RM recommends but should
624
+ * be safe to do, judging by years of testing results.
625
+ */
626
+ if (fsl_sai_dir_is_synced(sai, adir))
627
+ regmap_update_bits(sai->regmap, FSL_SAI_xCSR((!tx), ofs),
628
+ FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE);
535629
536
- regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx),
630
+ regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
537631 FSL_SAI_CSR_xIE_MASK, FSL_SAI_FLAGS);
538632 break;
539633 case SNDRV_PCM_TRIGGER_STOP:
540634 case SNDRV_PCM_TRIGGER_SUSPEND:
541635 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
542
- regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx),
636
+ regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
543637 FSL_SAI_CSR_FRDE, 0);
544
- regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx),
638
+ regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
545639 FSL_SAI_CSR_xIE_MASK, 0);
546640
547641 /* Check if the opposite FRDE is also disabled */
548
- regmap_read(sai->regmap, FSL_SAI_xCSR(!tx), &xcsr);
549
- if (!(xcsr & FSL_SAI_CSR_FRDE)) {
550
- /* Disable both directions and reset their FIFOs */
551
- regmap_update_bits(sai->regmap, FSL_SAI_TCSR,
552
- FSL_SAI_CSR_TERE, 0);
553
- regmap_update_bits(sai->regmap, FSL_SAI_RCSR,
554
- FSL_SAI_CSR_TERE, 0);
642
+ regmap_read(sai->regmap, FSL_SAI_xCSR(!tx, ofs), &xcsr);
555643
556
- /* TERE will remain set till the end of current frame */
557
- do {
558
- udelay(10);
559
- regmap_read(sai->regmap, FSL_SAI_xCSR(tx), &xcsr);
560
- } while (--count && xcsr & FSL_SAI_CSR_TERE);
644
+ /*
645
+ * If opposite stream provides clocks for synchronous mode and
646
+ * it is inactive, disable it before disabling the current one
647
+ */
648
+ if (fsl_sai_dir_is_synced(sai, adir) && !(xcsr & FSL_SAI_CSR_FRDE))
649
+ fsl_sai_config_disable(sai, adir);
561650
562
- regmap_update_bits(sai->regmap, FSL_SAI_TCSR,
563
- FSL_SAI_CSR_FR, FSL_SAI_CSR_FR);
564
- regmap_update_bits(sai->regmap, FSL_SAI_RCSR,
565
- FSL_SAI_CSR_FR, FSL_SAI_CSR_FR);
651
+ /*
652
+ * Disable current stream if either of:
653
+ * 1. current stream doesn't provide clocks for synchronous mode
654
+ * 2. current stream provides clocks for synchronous mode but no
655
+ * more stream is active.
656
+ */
657
+ if (!fsl_sai_dir_is_synced(sai, dir) || !(xcsr & FSL_SAI_CSR_FRDE))
658
+ fsl_sai_config_disable(sai, dir);
566659
567
- /*
568
- * For sai master mode, after several open/close sai,
569
- * there will be no frame clock, and can't recover
570
- * anymore. Add software reset to fix this issue.
571
- * This is a hardware bug, and will be fix in the
572
- * next sai version.
573
- */
574
- if (!sai->is_slave_mode) {
575
- /* Software Reset for both Tx and Rx */
576
- regmap_write(sai->regmap,
577
- FSL_SAI_TCSR, FSL_SAI_CSR_SR);
578
- regmap_write(sai->regmap,
579
- FSL_SAI_RCSR, FSL_SAI_CSR_SR);
580
- /* Clear SR bit to finish the reset */
581
- regmap_write(sai->regmap, FSL_SAI_TCSR, 0);
582
- regmap_write(sai->regmap, FSL_SAI_RCSR, 0);
583
- }
584
- }
585660 break;
586661 default:
587662 return -EINVAL;
....@@ -595,17 +670,17 @@
595670 {
596671 struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
597672 bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
598
- struct device *dev = &sai->pdev->dev;
599673 int ret;
600674
601
- ret = clk_prepare_enable(sai->bus_clk);
602
- if (ret) {
603
- dev_err(dev, "failed to enable bus clock: %d\n", ret);
604
- return ret;
605
- }
606
-
607
- regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx), FSL_SAI_CR3_TRCE,
608
- FSL_SAI_CR3_TRCE);
675
+ /*
676
+ * EDMA controller needs period size to be a multiple of
677
+ * tx/rx maxburst
678
+ */
679
+ if (sai->soc_data->use_edma)
680
+ snd_pcm_hw_constraint_step(substream->runtime, 0,
681
+ SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
682
+ tx ? sai->dma_params_tx.maxburst :
683
+ sai->dma_params_rx.maxburst);
609684
610685 ret = snd_pcm_hw_constraint_list(substream->runtime, 0,
611686 SNDRV_PCM_HW_PARAM_RATE, &fsl_sai_rate_constraints);
....@@ -613,18 +688,8 @@
613688 return ret;
614689 }
615690
616
-static void fsl_sai_shutdown(struct snd_pcm_substream *substream,
617
- struct snd_soc_dai *cpu_dai)
618
-{
619
- struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
620
- bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
621
-
622
- regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx), FSL_SAI_CR3_TRCE, 0);
623
-
624
- clk_disable_unprepare(sai->bus_clk);
625
-}
626
-
627691 static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = {
692
+ .set_bclk_ratio = fsl_sai_set_dai_bclk_ratio,
628693 .set_sysclk = fsl_sai_set_dai_sysclk,
629694 .set_fmt = fsl_sai_set_dai_fmt,
630695 .set_tdm_slot = fsl_sai_set_dai_tdm_slot,
....@@ -632,23 +697,25 @@
632697 .hw_free = fsl_sai_hw_free,
633698 .trigger = fsl_sai_trigger,
634699 .startup = fsl_sai_startup,
635
- .shutdown = fsl_sai_shutdown,
636700 };
637701
638702 static int fsl_sai_dai_probe(struct snd_soc_dai *cpu_dai)
639703 {
640704 struct fsl_sai *sai = dev_get_drvdata(cpu_dai->dev);
705
+ unsigned int ofs = sai->soc_data->reg_offset;
641706
642707 /* Software Reset for both Tx and Rx */
643
- regmap_write(sai->regmap, FSL_SAI_TCSR, FSL_SAI_CSR_SR);
644
- regmap_write(sai->regmap, FSL_SAI_RCSR, FSL_SAI_CSR_SR);
708
+ regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), FSL_SAI_CSR_SR);
709
+ regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), FSL_SAI_CSR_SR);
645710 /* Clear SR bit to finish the reset */
646
- regmap_write(sai->regmap, FSL_SAI_TCSR, 0);
647
- regmap_write(sai->regmap, FSL_SAI_RCSR, 0);
711
+ regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), 0);
712
+ regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), 0);
648713
649
- regmap_update_bits(sai->regmap, FSL_SAI_TCR1, FSL_SAI_CR1_RFW_MASK,
650
- FSL_SAI_MAXBURST_TX * 2);
651
- regmap_update_bits(sai->regmap, FSL_SAI_RCR1, FSL_SAI_CR1_RFW_MASK,
714
+ regmap_update_bits(sai->regmap, FSL_SAI_TCR1(ofs),
715
+ FSL_SAI_CR1_RFW_MASK(sai->soc_data->fifo_depth),
716
+ sai->soc_data->fifo_depth - FSL_SAI_MAXBURST_TX);
717
+ regmap_update_bits(sai->regmap, FSL_SAI_RCR1(ofs),
718
+ FSL_SAI_CR1_RFW_MASK(sai->soc_data->fifo_depth),
652719 FSL_SAI_MAXBURST_RX - 1);
653720
654721 snd_soc_dai_init_dma_data(cpu_dai, &sai->dma_params_tx,
....@@ -659,7 +726,7 @@
659726 return 0;
660727 }
661728
662
-static struct snd_soc_dai_driver fsl_sai_dai = {
729
+static struct snd_soc_dai_driver fsl_sai_dai_template = {
663730 .probe = fsl_sai_dai_probe,
664731 .playback = {
665732 .stream_name = "CPU-Playback",
....@@ -686,42 +753,104 @@
686753 .name = "fsl-sai",
687754 };
688755
689
-static struct reg_default fsl_sai_reg_defaults[] = {
690
- {FSL_SAI_TCR1, 0},
691
- {FSL_SAI_TCR2, 0},
692
- {FSL_SAI_TCR3, 0},
693
- {FSL_SAI_TCR4, 0},
694
- {FSL_SAI_TCR5, 0},
695
- {FSL_SAI_TDR, 0},
696
- {FSL_SAI_TMR, 0},
697
- {FSL_SAI_RCR1, 0},
698
- {FSL_SAI_RCR2, 0},
699
- {FSL_SAI_RCR3, 0},
700
- {FSL_SAI_RCR4, 0},
701
- {FSL_SAI_RCR5, 0},
702
- {FSL_SAI_RMR, 0},
756
+static struct reg_default fsl_sai_reg_defaults_ofs0[] = {
757
+ {FSL_SAI_TCR1(0), 0},
758
+ {FSL_SAI_TCR2(0), 0},
759
+ {FSL_SAI_TCR3(0), 0},
760
+ {FSL_SAI_TCR4(0), 0},
761
+ {FSL_SAI_TCR5(0), 0},
762
+ {FSL_SAI_TDR0, 0},
763
+ {FSL_SAI_TDR1, 0},
764
+ {FSL_SAI_TDR2, 0},
765
+ {FSL_SAI_TDR3, 0},
766
+ {FSL_SAI_TDR4, 0},
767
+ {FSL_SAI_TDR5, 0},
768
+ {FSL_SAI_TDR6, 0},
769
+ {FSL_SAI_TDR7, 0},
770
+ {FSL_SAI_TMR, 0},
771
+ {FSL_SAI_RCR1(0), 0},
772
+ {FSL_SAI_RCR2(0), 0},
773
+ {FSL_SAI_RCR3(0), 0},
774
+ {FSL_SAI_RCR4(0), 0},
775
+ {FSL_SAI_RCR5(0), 0},
776
+ {FSL_SAI_RMR, 0},
777
+};
778
+
779
+static struct reg_default fsl_sai_reg_defaults_ofs8[] = {
780
+ {FSL_SAI_TCR1(8), 0},
781
+ {FSL_SAI_TCR2(8), 0},
782
+ {FSL_SAI_TCR3(8), 0},
783
+ {FSL_SAI_TCR4(8), 0},
784
+ {FSL_SAI_TCR5(8), 0},
785
+ {FSL_SAI_TDR0, 0},
786
+ {FSL_SAI_TDR1, 0},
787
+ {FSL_SAI_TDR2, 0},
788
+ {FSL_SAI_TDR3, 0},
789
+ {FSL_SAI_TDR4, 0},
790
+ {FSL_SAI_TDR5, 0},
791
+ {FSL_SAI_TDR6, 0},
792
+ {FSL_SAI_TDR7, 0},
793
+ {FSL_SAI_TMR, 0},
794
+ {FSL_SAI_RCR1(8), 0},
795
+ {FSL_SAI_RCR2(8), 0},
796
+ {FSL_SAI_RCR3(8), 0},
797
+ {FSL_SAI_RCR4(8), 0},
798
+ {FSL_SAI_RCR5(8), 0},
799
+ {FSL_SAI_RMR, 0},
800
+ {FSL_SAI_MCTL, 0},
801
+ {FSL_SAI_MDIV, 0},
703802 };
704803
705804 static bool fsl_sai_readable_reg(struct device *dev, unsigned int reg)
706805 {
806
+ struct fsl_sai *sai = dev_get_drvdata(dev);
807
+ unsigned int ofs = sai->soc_data->reg_offset;
808
+
809
+ if (reg >= FSL_SAI_TCSR(ofs) && reg <= FSL_SAI_TCR5(ofs))
810
+ return true;
811
+
812
+ if (reg >= FSL_SAI_RCSR(ofs) && reg <= FSL_SAI_RCR5(ofs))
813
+ return true;
814
+
707815 switch (reg) {
708
- case FSL_SAI_TCSR:
709
- case FSL_SAI_TCR1:
710
- case FSL_SAI_TCR2:
711
- case FSL_SAI_TCR3:
712
- case FSL_SAI_TCR4:
713
- case FSL_SAI_TCR5:
714
- case FSL_SAI_TFR:
816
+ case FSL_SAI_TFR0:
817
+ case FSL_SAI_TFR1:
818
+ case FSL_SAI_TFR2:
819
+ case FSL_SAI_TFR3:
820
+ case FSL_SAI_TFR4:
821
+ case FSL_SAI_TFR5:
822
+ case FSL_SAI_TFR6:
823
+ case FSL_SAI_TFR7:
715824 case FSL_SAI_TMR:
716
- case FSL_SAI_RCSR:
717
- case FSL_SAI_RCR1:
718
- case FSL_SAI_RCR2:
719
- case FSL_SAI_RCR3:
720
- case FSL_SAI_RCR4:
721
- case FSL_SAI_RCR5:
722
- case FSL_SAI_RDR:
723
- case FSL_SAI_RFR:
825
+ case FSL_SAI_RDR0:
826
+ case FSL_SAI_RDR1:
827
+ case FSL_SAI_RDR2:
828
+ case FSL_SAI_RDR3:
829
+ case FSL_SAI_RDR4:
830
+ case FSL_SAI_RDR5:
831
+ case FSL_SAI_RDR6:
832
+ case FSL_SAI_RDR7:
833
+ case FSL_SAI_RFR0:
834
+ case FSL_SAI_RFR1:
835
+ case FSL_SAI_RFR2:
836
+ case FSL_SAI_RFR3:
837
+ case FSL_SAI_RFR4:
838
+ case FSL_SAI_RFR5:
839
+ case FSL_SAI_RFR6:
840
+ case FSL_SAI_RFR7:
724841 case FSL_SAI_RMR:
842
+ case FSL_SAI_MCTL:
843
+ case FSL_SAI_MDIV:
844
+ case FSL_SAI_VERID:
845
+ case FSL_SAI_PARAM:
846
+ case FSL_SAI_TTCTN:
847
+ case FSL_SAI_RTCTN:
848
+ case FSL_SAI_TTCTL:
849
+ case FSL_SAI_TBCTN:
850
+ case FSL_SAI_TTCAP:
851
+ case FSL_SAI_RTCTL:
852
+ case FSL_SAI_RBCTN:
853
+ case FSL_SAI_RTCAP:
725854 return true;
726855 default:
727856 return false;
....@@ -730,12 +859,41 @@
730859
731860 static bool fsl_sai_volatile_reg(struct device *dev, unsigned int reg)
732861 {
862
+ struct fsl_sai *sai = dev_get_drvdata(dev);
863
+ unsigned int ofs = sai->soc_data->reg_offset;
864
+
865
+ if (reg == FSL_SAI_TCSR(ofs) || reg == FSL_SAI_RCSR(ofs))
866
+ return true;
867
+
868
+ /* Set VERID and PARAM be volatile for reading value in probe */
869
+ if (ofs == 8 && (reg == FSL_SAI_VERID || reg == FSL_SAI_PARAM))
870
+ return true;
871
+
733872 switch (reg) {
734
- case FSL_SAI_TCSR:
735
- case FSL_SAI_RCSR:
736
- case FSL_SAI_TFR:
737
- case FSL_SAI_RFR:
738
- case FSL_SAI_RDR:
873
+ case FSL_SAI_TFR0:
874
+ case FSL_SAI_TFR1:
875
+ case FSL_SAI_TFR2:
876
+ case FSL_SAI_TFR3:
877
+ case FSL_SAI_TFR4:
878
+ case FSL_SAI_TFR5:
879
+ case FSL_SAI_TFR6:
880
+ case FSL_SAI_TFR7:
881
+ case FSL_SAI_RFR0:
882
+ case FSL_SAI_RFR1:
883
+ case FSL_SAI_RFR2:
884
+ case FSL_SAI_RFR3:
885
+ case FSL_SAI_RFR4:
886
+ case FSL_SAI_RFR5:
887
+ case FSL_SAI_RFR6:
888
+ case FSL_SAI_RFR7:
889
+ case FSL_SAI_RDR0:
890
+ case FSL_SAI_RDR1:
891
+ case FSL_SAI_RDR2:
892
+ case FSL_SAI_RDR3:
893
+ case FSL_SAI_RDR4:
894
+ case FSL_SAI_RDR5:
895
+ case FSL_SAI_RDR6:
896
+ case FSL_SAI_RDR7:
739897 return true;
740898 default:
741899 return false;
....@@ -744,41 +902,92 @@
744902
745903 static bool fsl_sai_writeable_reg(struct device *dev, unsigned int reg)
746904 {
905
+ struct fsl_sai *sai = dev_get_drvdata(dev);
906
+ unsigned int ofs = sai->soc_data->reg_offset;
907
+
908
+ if (reg >= FSL_SAI_TCSR(ofs) && reg <= FSL_SAI_TCR5(ofs))
909
+ return true;
910
+
911
+ if (reg >= FSL_SAI_RCSR(ofs) && reg <= FSL_SAI_RCR5(ofs))
912
+ return true;
913
+
747914 switch (reg) {
748
- case FSL_SAI_TCSR:
749
- case FSL_SAI_TCR1:
750
- case FSL_SAI_TCR2:
751
- case FSL_SAI_TCR3:
752
- case FSL_SAI_TCR4:
753
- case FSL_SAI_TCR5:
754
- case FSL_SAI_TDR:
915
+ case FSL_SAI_TDR0:
916
+ case FSL_SAI_TDR1:
917
+ case FSL_SAI_TDR2:
918
+ case FSL_SAI_TDR3:
919
+ case FSL_SAI_TDR4:
920
+ case FSL_SAI_TDR5:
921
+ case FSL_SAI_TDR6:
922
+ case FSL_SAI_TDR7:
755923 case FSL_SAI_TMR:
756
- case FSL_SAI_RCSR:
757
- case FSL_SAI_RCR1:
758
- case FSL_SAI_RCR2:
759
- case FSL_SAI_RCR3:
760
- case FSL_SAI_RCR4:
761
- case FSL_SAI_RCR5:
762924 case FSL_SAI_RMR:
925
+ case FSL_SAI_MCTL:
926
+ case FSL_SAI_MDIV:
927
+ case FSL_SAI_TTCTL:
928
+ case FSL_SAI_RTCTL:
763929 return true;
764930 default:
765931 return false;
766932 }
767933 }
768934
769
-static const struct regmap_config fsl_sai_regmap_config = {
935
+static struct regmap_config fsl_sai_regmap_config = {
770936 .reg_bits = 32,
771937 .reg_stride = 4,
772938 .val_bits = 32,
939
+ .fast_io = true,
773940
774941 .max_register = FSL_SAI_RMR,
775
- .reg_defaults = fsl_sai_reg_defaults,
776
- .num_reg_defaults = ARRAY_SIZE(fsl_sai_reg_defaults),
942
+ .reg_defaults = fsl_sai_reg_defaults_ofs0,
943
+ .num_reg_defaults = ARRAY_SIZE(fsl_sai_reg_defaults_ofs0),
777944 .readable_reg = fsl_sai_readable_reg,
778945 .volatile_reg = fsl_sai_volatile_reg,
779946 .writeable_reg = fsl_sai_writeable_reg,
780947 .cache_type = REGCACHE_FLAT,
781948 };
949
+
950
+static int fsl_sai_check_version(struct device *dev)
951
+{
952
+ struct fsl_sai *sai = dev_get_drvdata(dev);
953
+ unsigned char ofs = sai->soc_data->reg_offset;
954
+ unsigned int val;
955
+ int ret;
956
+
957
+ if (FSL_SAI_TCSR(ofs) == FSL_SAI_VERID)
958
+ return 0;
959
+
960
+ ret = regmap_read(sai->regmap, FSL_SAI_VERID, &val);
961
+ if (ret < 0)
962
+ return ret;
963
+
964
+ dev_dbg(dev, "VERID: 0x%016X\n", val);
965
+
966
+ sai->verid.major = (val & FSL_SAI_VERID_MAJOR_MASK) >>
967
+ FSL_SAI_VERID_MAJOR_SHIFT;
968
+ sai->verid.minor = (val & FSL_SAI_VERID_MINOR_MASK) >>
969
+ FSL_SAI_VERID_MINOR_SHIFT;
970
+ sai->verid.feature = val & FSL_SAI_VERID_FEATURE_MASK;
971
+
972
+ ret = regmap_read(sai->regmap, FSL_SAI_PARAM, &val);
973
+ if (ret < 0)
974
+ return ret;
975
+
976
+ dev_dbg(dev, "PARAM: 0x%016X\n", val);
977
+
978
+ /* Max slots per frame, power of 2 */
979
+ sai->param.slot_num = 1 <<
980
+ ((val & FSL_SAI_PARAM_SPF_MASK) >> FSL_SAI_PARAM_SPF_SHIFT);
981
+
982
+ /* Words per fifo, power of 2 */
983
+ sai->param.fifo_depth = 1 <<
984
+ ((val & FSL_SAI_PARAM_WPF_MASK) >> FSL_SAI_PARAM_WPF_SHIFT);
985
+
986
+ /* Number of datalines implemented */
987
+ sai->param.dataline = val & FSL_SAI_PARAM_DLN_MASK;
988
+
989
+ return 0;
990
+}
782991
783992 static int fsl_sai_probe(struct platform_device *pdev)
784993 {
....@@ -796,10 +1005,7 @@
7961005 return -ENOMEM;
7971006
7981007 sai->pdev = pdev;
799
-
800
- if (of_device_is_compatible(np, "fsl,imx6sx-sai") ||
801
- of_device_is_compatible(np, "fsl,imx6ul-sai"))
802
- sai->sai_on_imx = true;
1008
+ sai->soc_data = of_device_get_match_data(&pdev->dev);
8031009
8041010 sai->is_lsb_first = of_property_read_bool(np, "lsb-first");
8051011
....@@ -808,11 +1014,18 @@
8081014 if (IS_ERR(base))
8091015 return PTR_ERR(base);
8101016
1017
+ if (sai->soc_data->reg_offset == 8) {
1018
+ fsl_sai_regmap_config.reg_defaults = fsl_sai_reg_defaults_ofs8;
1019
+ fsl_sai_regmap_config.max_register = FSL_SAI_MDIV;
1020
+ fsl_sai_regmap_config.num_reg_defaults =
1021
+ ARRAY_SIZE(fsl_sai_reg_defaults_ofs8);
1022
+ }
1023
+
8111024 sai->regmap = devm_regmap_init_mmio_clk(&pdev->dev,
8121025 "bus", base, &fsl_sai_regmap_config);
8131026
8141027 /* Compatible with old DTB cases */
815
- if (IS_ERR(sai->regmap))
1028
+ if (IS_ERR(sai->regmap) && PTR_ERR(sai->regmap) != -EPROBE_DEFER)
8161029 sai->regmap = devm_regmap_init_mmio_clk(&pdev->dev,
8171030 "sai", base, &fsl_sai_regmap_config);
8181031 if (IS_ERR(sai->regmap)) {
....@@ -840,23 +1053,25 @@
8401053 }
8411054
8421055 irq = platform_get_irq(pdev, 0);
843
- if (irq < 0) {
844
- dev_err(&pdev->dev, "no irq for node %s\n", pdev->name);
1056
+ if (irq < 0)
8451057 return irq;
846
- }
8471058
848
- ret = devm_request_irq(&pdev->dev, irq, fsl_sai_isr, 0, np->name, sai);
1059
+ ret = devm_request_irq(&pdev->dev, irq, fsl_sai_isr, IRQF_SHARED,
1060
+ np->name, sai);
8491061 if (ret) {
8501062 dev_err(&pdev->dev, "failed to claim irq %u\n", irq);
8511063 return ret;
8521064 }
8531065
1066
+ memcpy(&sai->cpu_dai_drv, &fsl_sai_dai_template,
1067
+ sizeof(fsl_sai_dai_template));
1068
+
8541069 /* Sync Tx with Rx as default by following old DT binding */
8551070 sai->synchronous[RX] = true;
8561071 sai->synchronous[TX] = false;
857
- fsl_sai_dai.symmetric_rates = 1;
858
- fsl_sai_dai.symmetric_channels = 1;
859
- fsl_sai_dai.symmetric_samplebits = 1;
1072
+ sai->cpu_dai_drv.symmetric_rates = 1;
1073
+ sai->cpu_dai_drv.symmetric_channels = 1;
1074
+ sai->cpu_dai_drv.symmetric_samplebits = 1;
8601075
8611076 if (of_find_property(np, "fsl,sai-synchronous-rx", NULL) &&
8621077 of_find_property(np, "fsl,sai-asynchronous", NULL)) {
....@@ -873,9 +1088,9 @@
8731088 /* Discard all settings for asynchronous mode */
8741089 sai->synchronous[RX] = false;
8751090 sai->synchronous[TX] = false;
876
- fsl_sai_dai.symmetric_rates = 0;
877
- fsl_sai_dai.symmetric_channels = 0;
878
- fsl_sai_dai.symmetric_samplebits = 0;
1091
+ sai->cpu_dai_drv.symmetric_rates = 0;
1092
+ sai->cpu_dai_drv.symmetric_channels = 0;
1093
+ sai->cpu_dai_drv.symmetric_samplebits = 0;
8791094 }
8801095
8811096 if (of_find_property(np, "fsl,sai-mclk-direction-output", NULL) &&
....@@ -894,63 +1109,183 @@
8941109 MCLK_DIR(index));
8951110 }
8961111
897
- sai->dma_params_rx.addr = res->start + FSL_SAI_RDR;
898
- sai->dma_params_tx.addr = res->start + FSL_SAI_TDR;
1112
+ sai->dma_params_rx.addr = res->start + FSL_SAI_RDR0;
1113
+ sai->dma_params_tx.addr = res->start + FSL_SAI_TDR0;
8991114 sai->dma_params_rx.maxburst = FSL_SAI_MAXBURST_RX;
9001115 sai->dma_params_tx.maxburst = FSL_SAI_MAXBURST_TX;
9011116
9021117 platform_set_drvdata(pdev, sai);
9031118
904
- ret = devm_snd_soc_register_component(&pdev->dev, &fsl_component,
905
- &fsl_sai_dai, 1);
906
- if (ret)
907
- return ret;
1119
+ /* Get sai version */
1120
+ ret = fsl_sai_check_version(&pdev->dev);
1121
+ if (ret < 0)
1122
+ dev_warn(&pdev->dev, "Error reading SAI version: %d\n", ret);
9081123
909
- if (sai->sai_on_imx)
910
- return imx_pcm_dma_init(pdev, IMX_SAI_DMABUF_SIZE);
911
- else
912
- return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
1124
+ /* Select MCLK direction */
1125
+ if (of_find_property(np, "fsl,sai-mclk-direction-output", NULL) &&
1126
+ sai->verid.major >= 3 && sai->verid.minor >= 1) {
1127
+ regmap_update_bits(sai->regmap, FSL_SAI_MCTL,
1128
+ FSL_SAI_MCTL_MCLK_EN, FSL_SAI_MCTL_MCLK_EN);
1129
+ }
1130
+
1131
+ pm_runtime_enable(&pdev->dev);
1132
+ regcache_cache_only(sai->regmap, true);
1133
+
1134
+ ret = devm_snd_soc_register_component(&pdev->dev, &fsl_component,
1135
+ &sai->cpu_dai_drv, 1);
1136
+ if (ret)
1137
+ goto err_pm_disable;
1138
+
1139
+ if (sai->soc_data->use_imx_pcm) {
1140
+ ret = imx_pcm_dma_init(pdev, IMX_SAI_DMABUF_SIZE);
1141
+ if (ret)
1142
+ goto err_pm_disable;
1143
+ } else {
1144
+ ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
1145
+ if (ret)
1146
+ goto err_pm_disable;
1147
+ }
1148
+
1149
+ return ret;
1150
+
1151
+err_pm_disable:
1152
+ pm_runtime_disable(&pdev->dev);
1153
+
1154
+ return ret;
9131155 }
9141156
915
-static const struct of_device_id fsl_sai_ids[] = {
916
- { .compatible = "fsl,vf610-sai", },
917
- { .compatible = "fsl,imx6sx-sai", },
918
- { .compatible = "fsl,imx6ul-sai", },
919
- { /* sentinel */ }
920
-};
921
-MODULE_DEVICE_TABLE(of, fsl_sai_ids);
922
-
923
-#ifdef CONFIG_PM_SLEEP
924
-static int fsl_sai_suspend(struct device *dev)
1157
+static int fsl_sai_remove(struct platform_device *pdev)
9251158 {
926
- struct fsl_sai *sai = dev_get_drvdata(dev);
927
-
928
- regcache_cache_only(sai->regmap, true);
929
- regcache_mark_dirty(sai->regmap);
1159
+ pm_runtime_disable(&pdev->dev);
9301160
9311161 return 0;
9321162 }
9331163
934
-static int fsl_sai_resume(struct device *dev)
1164
+static const struct fsl_sai_soc_data fsl_sai_vf610_data = {
1165
+ .use_imx_pcm = false,
1166
+ .use_edma = false,
1167
+ .fifo_depth = 32,
1168
+ .reg_offset = 0,
1169
+};
1170
+
1171
+static const struct fsl_sai_soc_data fsl_sai_imx6sx_data = {
1172
+ .use_imx_pcm = true,
1173
+ .use_edma = false,
1174
+ .fifo_depth = 32,
1175
+ .reg_offset = 0,
1176
+};
1177
+
1178
+static const struct fsl_sai_soc_data fsl_sai_imx7ulp_data = {
1179
+ .use_imx_pcm = true,
1180
+ .use_edma = false,
1181
+ .fifo_depth = 16,
1182
+ .reg_offset = 8,
1183
+};
1184
+
1185
+static const struct fsl_sai_soc_data fsl_sai_imx8mq_data = {
1186
+ .use_imx_pcm = true,
1187
+ .use_edma = false,
1188
+ .fifo_depth = 128,
1189
+ .reg_offset = 8,
1190
+};
1191
+
1192
+static const struct fsl_sai_soc_data fsl_sai_imx8qm_data = {
1193
+ .use_imx_pcm = true,
1194
+ .use_edma = true,
1195
+ .fifo_depth = 64,
1196
+ .reg_offset = 0,
1197
+};
1198
+
1199
+static const struct of_device_id fsl_sai_ids[] = {
1200
+ { .compatible = "fsl,vf610-sai", .data = &fsl_sai_vf610_data },
1201
+ { .compatible = "fsl,imx6sx-sai", .data = &fsl_sai_imx6sx_data },
1202
+ { .compatible = "fsl,imx6ul-sai", .data = &fsl_sai_imx6sx_data },
1203
+ { .compatible = "fsl,imx7ulp-sai", .data = &fsl_sai_imx7ulp_data },
1204
+ { .compatible = "fsl,imx8mq-sai", .data = &fsl_sai_imx8mq_data },
1205
+ { .compatible = "fsl,imx8qm-sai", .data = &fsl_sai_imx8qm_data },
1206
+ { /* sentinel */ }
1207
+};
1208
+MODULE_DEVICE_TABLE(of, fsl_sai_ids);
1209
+
1210
+#ifdef CONFIG_PM
1211
+static int fsl_sai_runtime_suspend(struct device *dev)
9351212 {
9361213 struct fsl_sai *sai = dev_get_drvdata(dev);
9371214
938
- regcache_cache_only(sai->regmap, false);
939
- regmap_write(sai->regmap, FSL_SAI_TCSR, FSL_SAI_CSR_SR);
940
- regmap_write(sai->regmap, FSL_SAI_RCSR, FSL_SAI_CSR_SR);
941
- usleep_range(1000, 2000);
942
- regmap_write(sai->regmap, FSL_SAI_TCSR, 0);
943
- regmap_write(sai->regmap, FSL_SAI_RCSR, 0);
944
- return regcache_sync(sai->regmap);
1215
+ if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_CAPTURE))
1216
+ clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[0]]);
1217
+
1218
+ if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_PLAYBACK))
1219
+ clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[1]]);
1220
+
1221
+ clk_disable_unprepare(sai->bus_clk);
1222
+
1223
+ regcache_cache_only(sai->regmap, true);
1224
+
1225
+ return 0;
9451226 }
946
-#endif /* CONFIG_PM_SLEEP */
1227
+
1228
+static int fsl_sai_runtime_resume(struct device *dev)
1229
+{
1230
+ struct fsl_sai *sai = dev_get_drvdata(dev);
1231
+ unsigned int ofs = sai->soc_data->reg_offset;
1232
+ int ret;
1233
+
1234
+ ret = clk_prepare_enable(sai->bus_clk);
1235
+ if (ret) {
1236
+ dev_err(dev, "failed to enable bus clock: %d\n", ret);
1237
+ return ret;
1238
+ }
1239
+
1240
+ if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_PLAYBACK)) {
1241
+ ret = clk_prepare_enable(sai->mclk_clk[sai->mclk_id[1]]);
1242
+ if (ret)
1243
+ goto disable_bus_clk;
1244
+ }
1245
+
1246
+ if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_CAPTURE)) {
1247
+ ret = clk_prepare_enable(sai->mclk_clk[sai->mclk_id[0]]);
1248
+ if (ret)
1249
+ goto disable_tx_clk;
1250
+ }
1251
+
1252
+ regcache_cache_only(sai->regmap, false);
1253
+ regcache_mark_dirty(sai->regmap);
1254
+ regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), FSL_SAI_CSR_SR);
1255
+ regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), FSL_SAI_CSR_SR);
1256
+ usleep_range(1000, 2000);
1257
+ regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), 0);
1258
+ regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), 0);
1259
+
1260
+ ret = regcache_sync(sai->regmap);
1261
+ if (ret)
1262
+ goto disable_rx_clk;
1263
+
1264
+ return 0;
1265
+
1266
+disable_rx_clk:
1267
+ if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_CAPTURE))
1268
+ clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[0]]);
1269
+disable_tx_clk:
1270
+ if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_PLAYBACK))
1271
+ clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[1]]);
1272
+disable_bus_clk:
1273
+ clk_disable_unprepare(sai->bus_clk);
1274
+
1275
+ return ret;
1276
+}
1277
+#endif /* CONFIG_PM */
9471278
9481279 static const struct dev_pm_ops fsl_sai_pm_ops = {
949
- SET_SYSTEM_SLEEP_PM_OPS(fsl_sai_suspend, fsl_sai_resume)
1280
+ SET_RUNTIME_PM_OPS(fsl_sai_runtime_suspend,
1281
+ fsl_sai_runtime_resume, NULL)
1282
+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
1283
+ pm_runtime_force_resume)
9501284 };
9511285
9521286 static struct platform_driver fsl_sai_driver = {
9531287 .probe = fsl_sai_probe,
1288
+ .remove = fsl_sai_remove,
9541289 .driver = {
9551290 .name = "fsl-sai",
9561291 .pm = &fsl_sai_pm_ops,