forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-11 1f93a7dfd1f8d5ff7a5c53246c7534fe2332d6f4
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,6 +223,7 @@
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
....@@ -285,9 +318,9 @@
285318 return -EINVAL;
286319 }
287320
288
- regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx),
321
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx, ofs),
289322 FSL_SAI_CR2_BCP | FSL_SAI_CR2_BCD_MSTR, val_cr2);
290
- regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx),
323
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs),
291324 FSL_SAI_CR4_MF | FSL_SAI_CR4_FSE |
292325 FSL_SAI_CR4_FSP | FSL_SAI_CR4_FSD_MSTR, val_cr4);
293326
....@@ -314,8 +347,11 @@
314347 static int fsl_sai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq)
315348 {
316349 struct fsl_sai *sai = snd_soc_dai_get_drvdata(dai);
350
+ unsigned int ofs = sai->soc_data->reg_offset;
317351 unsigned long clk_rate;
318352 u32 savediv = 0, ratio, savesub = freq;
353
+ int adir = tx ? RX : TX;
354
+ int dir = tx ? TX : RX;
319355 u32 id;
320356 int ret = 0;
321357
....@@ -374,19 +410,17 @@
374410 * 4) For Tx and Rx are both Synchronous with another SAI, we just
375411 * ignore it.
376412 */
377
- if ((sai->synchronous[TX] && !sai->synchronous[RX]) ||
378
- (!tx && !sai->synchronous[RX])) {
379
- regmap_update_bits(sai->regmap, FSL_SAI_RCR2,
413
+ if (fsl_sai_dir_is_synced(sai, adir)) {
414
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR2(!tx, ofs),
380415 FSL_SAI_CR2_MSEL_MASK,
381416 FSL_SAI_CR2_MSEL(sai->mclk_id[tx]));
382
- regmap_update_bits(sai->regmap, FSL_SAI_RCR2,
417
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR2(!tx, ofs),
383418 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,
419
+ } else if (!sai->synchronous[dir]) {
420
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx, ofs),
387421 FSL_SAI_CR2_MSEL_MASK,
388422 FSL_SAI_CR2_MSEL(sai->mclk_id[tx]));
389
- regmap_update_bits(sai->regmap, FSL_SAI_TCR2,
423
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx, ofs),
390424 FSL_SAI_CR2_DIV_MASK, savediv - 1);
391425 }
392426
....@@ -401,12 +435,15 @@
401435 struct snd_soc_dai *cpu_dai)
402436 {
403437 struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
438
+ unsigned int ofs = sai->soc_data->reg_offset;
404439 bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
405440 unsigned int channels = params_channels(params);
406441 u32 word_width = params_width(params);
407442 u32 val_cr4 = 0, val_cr5 = 0;
408443 u32 slots = (channels == 1) ? 2 : channels;
409444 u32 slot_width = word_width;
445
+ int adir = tx ? RX : TX;
446
+ u32 pins;
410447 int ret;
411448
412449 if (sai->slots)
....@@ -415,9 +452,17 @@
415452 if (sai->slot_width)
416453 slot_width = sai->slot_width;
417454
455
+ pins = DIV_ROUND_UP(channels, slots);
456
+
418457 if (!sai->is_slave_mode) {
419
- ret = fsl_sai_set_bclk(cpu_dai, tx,
420
- slots * slot_width * params_rate(params));
458
+ if (sai->bclk_ratio)
459
+ ret = fsl_sai_set_bclk(cpu_dai, tx,
460
+ sai->bclk_ratio *
461
+ params_rate(params));
462
+ else
463
+ ret = fsl_sai_set_bclk(cpu_dai, tx,
464
+ slots * slot_width *
465
+ params_rate(params));
421466 if (ret)
422467 return ret;
423468
....@@ -444,42 +489,38 @@
444489
445490 val_cr4 |= FSL_SAI_CR4_FRSZ(slots);
446491
492
+ /* Set to output mode to avoid tri-stated data pins */
493
+ if (tx)
494
+ val_cr4 |= FSL_SAI_CR4_CHMOD;
495
+
447496 /*
448497 * For SAI master mode, when Tx(Rx) sync with Rx(Tx) clock, Rx(Tx) will
449498 * 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.
499
+ * RCR5(TCR5) for playback(capture), or there will be sync error.
452500 */
453501
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
- }
502
+ if (!sai->is_slave_mode && fsl_sai_dir_is_synced(sai, adir)) {
503
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR4(!tx, ofs),
504
+ FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK |
505
+ FSL_SAI_CR4_CHMOD_MASK,
506
+ val_cr4);
507
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR5(!tx, ofs),
508
+ FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK |
509
+ FSL_SAI_CR5_FBT_MASK, val_cr5);
474510 }
475511
476
- regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx),
477
- FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK,
512
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx, ofs),
513
+ FSL_SAI_CR3_TRCE_MASK,
514
+ FSL_SAI_CR3_TRCE((1 << pins) - 1));
515
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs),
516
+ FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK |
517
+ FSL_SAI_CR4_CHMOD_MASK,
478518 val_cr4);
479
- regmap_update_bits(sai->regmap, FSL_SAI_xCR5(tx),
519
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR5(tx, ofs),
480520 FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK |
481521 FSL_SAI_CR5_FBT_MASK, val_cr5);
482
- regmap_write(sai->regmap, FSL_SAI_xMR(tx), ~0UL - ((1 << channels) - 1));
522
+ regmap_write(sai->regmap, FSL_SAI_xMR(tx),
523
+ ~0UL - ((1 << min(channels, slots)) - 1));
483524
484525 return 0;
485526 }
....@@ -489,6 +530,10 @@
489530 {
490531 struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
491532 bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
533
+ unsigned int ofs = sai->soc_data->reg_offset;
534
+
535
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx, ofs),
536
+ FSL_SAI_CR3_TRCE_MASK, 0);
492537
493538 if (!sai->is_slave_mode &&
494539 sai->mclk_streams & BIT(substream->stream)) {
....@@ -499,22 +544,58 @@
499544 return 0;
500545 }
501546
547
+static void fsl_sai_config_disable(struct fsl_sai *sai, int dir)
548
+{
549
+ unsigned int ofs = sai->soc_data->reg_offset;
550
+ bool tx = dir == TX;
551
+ u32 xcsr, count = 100;
552
+
553
+ regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
554
+ FSL_SAI_CSR_TERE, 0);
555
+
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, ofs), &xcsr);
560
+ } while (--count && xcsr & FSL_SAI_CSR_TERE);
561
+
562
+ regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
563
+ FSL_SAI_CSR_FR, FSL_SAI_CSR_FR);
564
+
565
+ /*
566
+ * For sai master mode, after several open/close sai,
567
+ * there will be no frame clock, and can't recover
568
+ * anymore. Add software reset to fix this issue.
569
+ * This is a hardware bug, and will be fix in the
570
+ * next sai version.
571
+ */
572
+ if (!sai->is_slave_mode) {
573
+ /* Software Reset */
574
+ regmap_write(sai->regmap, FSL_SAI_xCSR(tx, ofs), FSL_SAI_CSR_SR);
575
+ /* Clear SR bit to finish the reset */
576
+ regmap_write(sai->regmap, FSL_SAI_xCSR(tx, ofs), 0);
577
+ }
578
+}
502579
503580 static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
504581 struct snd_soc_dai *cpu_dai)
505582 {
506583 struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
584
+ unsigned int ofs = sai->soc_data->reg_offset;
585
+
507586 bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
508
- u32 xcsr, count = 100;
587
+ int adir = tx ? RX : TX;
588
+ int dir = tx ? TX : RX;
589
+ u32 xcsr;
509590
510591 /*
511592 * Asynchronous mode: Clear SYNC for both Tx and Rx.
512593 * Rx sync with Tx clocks: Clear SYNC for Tx, set it for Rx.
513594 * Tx sync with Rx clocks: Clear SYNC for Rx, set it for Tx.
514595 */
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,
596
+ regmap_update_bits(sai->regmap, FSL_SAI_TCR2(ofs), FSL_SAI_CR2_SYNC,
597
+ sai->synchronous[TX] ? FSL_SAI_CR2_SYNC : 0);
598
+ regmap_update_bits(sai->regmap, FSL_SAI_RCR2(ofs), FSL_SAI_CR2_SYNC,
518599 sai->synchronous[RX] ? FSL_SAI_CR2_SYNC : 0);
519600
520601 /*
....@@ -525,63 +606,56 @@
525606 case SNDRV_PCM_TRIGGER_START:
526607 case SNDRV_PCM_TRIGGER_RESUME:
527608 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
528
- regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx),
609
+ regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
529610 FSL_SAI_CSR_FRDE, FSL_SAI_CSR_FRDE);
530611
531
- regmap_update_bits(sai->regmap, FSL_SAI_RCSR,
612
+ regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
532613 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);
614
+ /*
615
+ * Enable the opposite direction for synchronous mode
616
+ * 1. Tx sync with Rx: only set RE for Rx; set TE & RE for Tx
617
+ * 2. Rx sync with Tx: only set TE for Tx; set RE & TE for Rx
618
+ *
619
+ * RM recommends to enable RE after TE for case 1 and to enable
620
+ * TE after RE for case 2, but we here may not always guarantee
621
+ * that happens: "arecord 1.wav; aplay 2.wav" in case 1 enables
622
+ * TE after RE, which is against what RM recommends but should
623
+ * be safe to do, judging by years of testing results.
624
+ */
625
+ if (fsl_sai_dir_is_synced(sai, adir))
626
+ regmap_update_bits(sai->regmap, FSL_SAI_xCSR((!tx), ofs),
627
+ FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE);
535628
536
- regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx),
629
+ regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
537630 FSL_SAI_CSR_xIE_MASK, FSL_SAI_FLAGS);
538631 break;
539632 case SNDRV_PCM_TRIGGER_STOP:
540633 case SNDRV_PCM_TRIGGER_SUSPEND:
541634 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
542
- regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx),
635
+ regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
543636 FSL_SAI_CSR_FRDE, 0);
544
- regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx),
637
+ regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
545638 FSL_SAI_CSR_xIE_MASK, 0);
546639
547640 /* 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);
641
+ regmap_read(sai->regmap, FSL_SAI_xCSR(!tx, ofs), &xcsr);
555642
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);
643
+ /*
644
+ * If opposite stream provides clocks for synchronous mode and
645
+ * it is inactive, disable it before disabling the current one
646
+ */
647
+ if (fsl_sai_dir_is_synced(sai, adir) && !(xcsr & FSL_SAI_CSR_FRDE))
648
+ fsl_sai_config_disable(sai, adir);
561649
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);
650
+ /*
651
+ * Disable current stream if either of:
652
+ * 1. current stream doesn't provide clocks for synchronous mode
653
+ * 2. current stream provides clocks for synchronous mode but no
654
+ * more stream is active.
655
+ */
656
+ if (!fsl_sai_dir_is_synced(sai, dir) || !(xcsr & FSL_SAI_CSR_FRDE))
657
+ fsl_sai_config_disable(sai, dir);
566658
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
- }
585659 break;
586660 default:
587661 return -EINVAL;
....@@ -595,17 +669,17 @@
595669 {
596670 struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
597671 bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
598
- struct device *dev = &sai->pdev->dev;
599672 int ret;
600673
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);
674
+ /*
675
+ * EDMA controller needs period size to be a multiple of
676
+ * tx/rx maxburst
677
+ */
678
+ if (sai->soc_data->use_edma)
679
+ snd_pcm_hw_constraint_step(substream->runtime, 0,
680
+ SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
681
+ tx ? sai->dma_params_tx.maxburst :
682
+ sai->dma_params_rx.maxburst);
609683
610684 ret = snd_pcm_hw_constraint_list(substream->runtime, 0,
611685 SNDRV_PCM_HW_PARAM_RATE, &fsl_sai_rate_constraints);
....@@ -613,18 +687,8 @@
613687 return ret;
614688 }
615689
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
-
627690 static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = {
691
+ .set_bclk_ratio = fsl_sai_set_dai_bclk_ratio,
628692 .set_sysclk = fsl_sai_set_dai_sysclk,
629693 .set_fmt = fsl_sai_set_dai_fmt,
630694 .set_tdm_slot = fsl_sai_set_dai_tdm_slot,
....@@ -632,23 +696,25 @@
632696 .hw_free = fsl_sai_hw_free,
633697 .trigger = fsl_sai_trigger,
634698 .startup = fsl_sai_startup,
635
- .shutdown = fsl_sai_shutdown,
636699 };
637700
638701 static int fsl_sai_dai_probe(struct snd_soc_dai *cpu_dai)
639702 {
640703 struct fsl_sai *sai = dev_get_drvdata(cpu_dai->dev);
704
+ unsigned int ofs = sai->soc_data->reg_offset;
641705
642706 /* 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);
707
+ regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), FSL_SAI_CSR_SR);
708
+ regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), FSL_SAI_CSR_SR);
645709 /* 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);
710
+ regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), 0);
711
+ regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), 0);
648712
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,
713
+ regmap_update_bits(sai->regmap, FSL_SAI_TCR1(ofs),
714
+ FSL_SAI_CR1_RFW_MASK(sai->soc_data->fifo_depth),
715
+ sai->soc_data->fifo_depth - FSL_SAI_MAXBURST_TX);
716
+ regmap_update_bits(sai->regmap, FSL_SAI_RCR1(ofs),
717
+ FSL_SAI_CR1_RFW_MASK(sai->soc_data->fifo_depth),
652718 FSL_SAI_MAXBURST_RX - 1);
653719
654720 snd_soc_dai_init_dma_data(cpu_dai, &sai->dma_params_tx,
....@@ -659,7 +725,7 @@
659725 return 0;
660726 }
661727
662
-static struct snd_soc_dai_driver fsl_sai_dai = {
728
+static struct snd_soc_dai_driver fsl_sai_dai_template = {
663729 .probe = fsl_sai_dai_probe,
664730 .playback = {
665731 .stream_name = "CPU-Playback",
....@@ -686,42 +752,104 @@
686752 .name = "fsl-sai",
687753 };
688754
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},
755
+static struct reg_default fsl_sai_reg_defaults_ofs0[] = {
756
+ {FSL_SAI_TCR1(0), 0},
757
+ {FSL_SAI_TCR2(0), 0},
758
+ {FSL_SAI_TCR3(0), 0},
759
+ {FSL_SAI_TCR4(0), 0},
760
+ {FSL_SAI_TCR5(0), 0},
761
+ {FSL_SAI_TDR0, 0},
762
+ {FSL_SAI_TDR1, 0},
763
+ {FSL_SAI_TDR2, 0},
764
+ {FSL_SAI_TDR3, 0},
765
+ {FSL_SAI_TDR4, 0},
766
+ {FSL_SAI_TDR5, 0},
767
+ {FSL_SAI_TDR6, 0},
768
+ {FSL_SAI_TDR7, 0},
769
+ {FSL_SAI_TMR, 0},
770
+ {FSL_SAI_RCR1(0), 0},
771
+ {FSL_SAI_RCR2(0), 0},
772
+ {FSL_SAI_RCR3(0), 0},
773
+ {FSL_SAI_RCR4(0), 0},
774
+ {FSL_SAI_RCR5(0), 0},
775
+ {FSL_SAI_RMR, 0},
776
+};
777
+
778
+static struct reg_default fsl_sai_reg_defaults_ofs8[] = {
779
+ {FSL_SAI_TCR1(8), 0},
780
+ {FSL_SAI_TCR2(8), 0},
781
+ {FSL_SAI_TCR3(8), 0},
782
+ {FSL_SAI_TCR4(8), 0},
783
+ {FSL_SAI_TCR5(8), 0},
784
+ {FSL_SAI_TDR0, 0},
785
+ {FSL_SAI_TDR1, 0},
786
+ {FSL_SAI_TDR2, 0},
787
+ {FSL_SAI_TDR3, 0},
788
+ {FSL_SAI_TDR4, 0},
789
+ {FSL_SAI_TDR5, 0},
790
+ {FSL_SAI_TDR6, 0},
791
+ {FSL_SAI_TDR7, 0},
792
+ {FSL_SAI_TMR, 0},
793
+ {FSL_SAI_RCR1(8), 0},
794
+ {FSL_SAI_RCR2(8), 0},
795
+ {FSL_SAI_RCR3(8), 0},
796
+ {FSL_SAI_RCR4(8), 0},
797
+ {FSL_SAI_RCR5(8), 0},
798
+ {FSL_SAI_RMR, 0},
799
+ {FSL_SAI_MCTL, 0},
800
+ {FSL_SAI_MDIV, 0},
703801 };
704802
705803 static bool fsl_sai_readable_reg(struct device *dev, unsigned int reg)
706804 {
805
+ struct fsl_sai *sai = dev_get_drvdata(dev);
806
+ unsigned int ofs = sai->soc_data->reg_offset;
807
+
808
+ if (reg >= FSL_SAI_TCSR(ofs) && reg <= FSL_SAI_TCR5(ofs))
809
+ return true;
810
+
811
+ if (reg >= FSL_SAI_RCSR(ofs) && reg <= FSL_SAI_RCR5(ofs))
812
+ return true;
813
+
707814 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:
815
+ case FSL_SAI_TFR0:
816
+ case FSL_SAI_TFR1:
817
+ case FSL_SAI_TFR2:
818
+ case FSL_SAI_TFR3:
819
+ case FSL_SAI_TFR4:
820
+ case FSL_SAI_TFR5:
821
+ case FSL_SAI_TFR6:
822
+ case FSL_SAI_TFR7:
715823 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:
824
+ case FSL_SAI_RDR0:
825
+ case FSL_SAI_RDR1:
826
+ case FSL_SAI_RDR2:
827
+ case FSL_SAI_RDR3:
828
+ case FSL_SAI_RDR4:
829
+ case FSL_SAI_RDR5:
830
+ case FSL_SAI_RDR6:
831
+ case FSL_SAI_RDR7:
832
+ case FSL_SAI_RFR0:
833
+ case FSL_SAI_RFR1:
834
+ case FSL_SAI_RFR2:
835
+ case FSL_SAI_RFR3:
836
+ case FSL_SAI_RFR4:
837
+ case FSL_SAI_RFR5:
838
+ case FSL_SAI_RFR6:
839
+ case FSL_SAI_RFR7:
724840 case FSL_SAI_RMR:
841
+ case FSL_SAI_MCTL:
842
+ case FSL_SAI_MDIV:
843
+ case FSL_SAI_VERID:
844
+ case FSL_SAI_PARAM:
845
+ case FSL_SAI_TTCTN:
846
+ case FSL_SAI_RTCTN:
847
+ case FSL_SAI_TTCTL:
848
+ case FSL_SAI_TBCTN:
849
+ case FSL_SAI_TTCAP:
850
+ case FSL_SAI_RTCTL:
851
+ case FSL_SAI_RBCTN:
852
+ case FSL_SAI_RTCAP:
725853 return true;
726854 default:
727855 return false;
....@@ -730,12 +858,41 @@
730858
731859 static bool fsl_sai_volatile_reg(struct device *dev, unsigned int reg)
732860 {
861
+ struct fsl_sai *sai = dev_get_drvdata(dev);
862
+ unsigned int ofs = sai->soc_data->reg_offset;
863
+
864
+ if (reg == FSL_SAI_TCSR(ofs) || reg == FSL_SAI_RCSR(ofs))
865
+ return true;
866
+
867
+ /* Set VERID and PARAM be volatile for reading value in probe */
868
+ if (ofs == 8 && (reg == FSL_SAI_VERID || reg == FSL_SAI_PARAM))
869
+ return true;
870
+
733871 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:
872
+ case FSL_SAI_TFR0:
873
+ case FSL_SAI_TFR1:
874
+ case FSL_SAI_TFR2:
875
+ case FSL_SAI_TFR3:
876
+ case FSL_SAI_TFR4:
877
+ case FSL_SAI_TFR5:
878
+ case FSL_SAI_TFR6:
879
+ case FSL_SAI_TFR7:
880
+ case FSL_SAI_RFR0:
881
+ case FSL_SAI_RFR1:
882
+ case FSL_SAI_RFR2:
883
+ case FSL_SAI_RFR3:
884
+ case FSL_SAI_RFR4:
885
+ case FSL_SAI_RFR5:
886
+ case FSL_SAI_RFR6:
887
+ case FSL_SAI_RFR7:
888
+ case FSL_SAI_RDR0:
889
+ case FSL_SAI_RDR1:
890
+ case FSL_SAI_RDR2:
891
+ case FSL_SAI_RDR3:
892
+ case FSL_SAI_RDR4:
893
+ case FSL_SAI_RDR5:
894
+ case FSL_SAI_RDR6:
895
+ case FSL_SAI_RDR7:
739896 return true;
740897 default:
741898 return false;
....@@ -744,41 +901,92 @@
744901
745902 static bool fsl_sai_writeable_reg(struct device *dev, unsigned int reg)
746903 {
904
+ struct fsl_sai *sai = dev_get_drvdata(dev);
905
+ unsigned int ofs = sai->soc_data->reg_offset;
906
+
907
+ if (reg >= FSL_SAI_TCSR(ofs) && reg <= FSL_SAI_TCR5(ofs))
908
+ return true;
909
+
910
+ if (reg >= FSL_SAI_RCSR(ofs) && reg <= FSL_SAI_RCR5(ofs))
911
+ return true;
912
+
747913 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:
914
+ case FSL_SAI_TDR0:
915
+ case FSL_SAI_TDR1:
916
+ case FSL_SAI_TDR2:
917
+ case FSL_SAI_TDR3:
918
+ case FSL_SAI_TDR4:
919
+ case FSL_SAI_TDR5:
920
+ case FSL_SAI_TDR6:
921
+ case FSL_SAI_TDR7:
755922 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:
762923 case FSL_SAI_RMR:
924
+ case FSL_SAI_MCTL:
925
+ case FSL_SAI_MDIV:
926
+ case FSL_SAI_TTCTL:
927
+ case FSL_SAI_RTCTL:
763928 return true;
764929 default:
765930 return false;
766931 }
767932 }
768933
769
-static const struct regmap_config fsl_sai_regmap_config = {
934
+static struct regmap_config fsl_sai_regmap_config = {
770935 .reg_bits = 32,
771936 .reg_stride = 4,
772937 .val_bits = 32,
938
+ .fast_io = true,
773939
774940 .max_register = FSL_SAI_RMR,
775
- .reg_defaults = fsl_sai_reg_defaults,
776
- .num_reg_defaults = ARRAY_SIZE(fsl_sai_reg_defaults),
941
+ .reg_defaults = fsl_sai_reg_defaults_ofs0,
942
+ .num_reg_defaults = ARRAY_SIZE(fsl_sai_reg_defaults_ofs0),
777943 .readable_reg = fsl_sai_readable_reg,
778944 .volatile_reg = fsl_sai_volatile_reg,
779945 .writeable_reg = fsl_sai_writeable_reg,
780946 .cache_type = REGCACHE_FLAT,
781947 };
948
+
949
+static int fsl_sai_check_version(struct device *dev)
950
+{
951
+ struct fsl_sai *sai = dev_get_drvdata(dev);
952
+ unsigned char ofs = sai->soc_data->reg_offset;
953
+ unsigned int val;
954
+ int ret;
955
+
956
+ if (FSL_SAI_TCSR(ofs) == FSL_SAI_VERID)
957
+ return 0;
958
+
959
+ ret = regmap_read(sai->regmap, FSL_SAI_VERID, &val);
960
+ if (ret < 0)
961
+ return ret;
962
+
963
+ dev_dbg(dev, "VERID: 0x%016X\n", val);
964
+
965
+ sai->verid.major = (val & FSL_SAI_VERID_MAJOR_MASK) >>
966
+ FSL_SAI_VERID_MAJOR_SHIFT;
967
+ sai->verid.minor = (val & FSL_SAI_VERID_MINOR_MASK) >>
968
+ FSL_SAI_VERID_MINOR_SHIFT;
969
+ sai->verid.feature = val & FSL_SAI_VERID_FEATURE_MASK;
970
+
971
+ ret = regmap_read(sai->regmap, FSL_SAI_PARAM, &val);
972
+ if (ret < 0)
973
+ return ret;
974
+
975
+ dev_dbg(dev, "PARAM: 0x%016X\n", val);
976
+
977
+ /* Max slots per frame, power of 2 */
978
+ sai->param.slot_num = 1 <<
979
+ ((val & FSL_SAI_PARAM_SPF_MASK) >> FSL_SAI_PARAM_SPF_SHIFT);
980
+
981
+ /* Words per fifo, power of 2 */
982
+ sai->param.fifo_depth = 1 <<
983
+ ((val & FSL_SAI_PARAM_WPF_MASK) >> FSL_SAI_PARAM_WPF_SHIFT);
984
+
985
+ /* Number of datalines implemented */
986
+ sai->param.dataline = val & FSL_SAI_PARAM_DLN_MASK;
987
+
988
+ return 0;
989
+}
782990
783991 static int fsl_sai_probe(struct platform_device *pdev)
784992 {
....@@ -796,10 +1004,7 @@
7961004 return -ENOMEM;
7971005
7981006 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;
1007
+ sai->soc_data = of_device_get_match_data(&pdev->dev);
8031008
8041009 sai->is_lsb_first = of_property_read_bool(np, "lsb-first");
8051010
....@@ -808,11 +1013,18 @@
8081013 if (IS_ERR(base))
8091014 return PTR_ERR(base);
8101015
1016
+ if (sai->soc_data->reg_offset == 8) {
1017
+ fsl_sai_regmap_config.reg_defaults = fsl_sai_reg_defaults_ofs8;
1018
+ fsl_sai_regmap_config.max_register = FSL_SAI_MDIV;
1019
+ fsl_sai_regmap_config.num_reg_defaults =
1020
+ ARRAY_SIZE(fsl_sai_reg_defaults_ofs8);
1021
+ }
1022
+
8111023 sai->regmap = devm_regmap_init_mmio_clk(&pdev->dev,
8121024 "bus", base, &fsl_sai_regmap_config);
8131025
8141026 /* Compatible with old DTB cases */
815
- if (IS_ERR(sai->regmap))
1027
+ if (IS_ERR(sai->regmap) && PTR_ERR(sai->regmap) != -EPROBE_DEFER)
8161028 sai->regmap = devm_regmap_init_mmio_clk(&pdev->dev,
8171029 "sai", base, &fsl_sai_regmap_config);
8181030 if (IS_ERR(sai->regmap)) {
....@@ -840,23 +1052,25 @@
8401052 }
8411053
8421054 irq = platform_get_irq(pdev, 0);
843
- if (irq < 0) {
844
- dev_err(&pdev->dev, "no irq for node %s\n", pdev->name);
1055
+ if (irq < 0)
8451056 return irq;
846
- }
8471057
848
- ret = devm_request_irq(&pdev->dev, irq, fsl_sai_isr, 0, np->name, sai);
1058
+ ret = devm_request_irq(&pdev->dev, irq, fsl_sai_isr, IRQF_SHARED,
1059
+ np->name, sai);
8491060 if (ret) {
8501061 dev_err(&pdev->dev, "failed to claim irq %u\n", irq);
8511062 return ret;
8521063 }
8531064
1065
+ memcpy(&sai->cpu_dai_drv, &fsl_sai_dai_template,
1066
+ sizeof(fsl_sai_dai_template));
1067
+
8541068 /* Sync Tx with Rx as default by following old DT binding */
8551069 sai->synchronous[RX] = true;
8561070 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;
1071
+ sai->cpu_dai_drv.symmetric_rates = 1;
1072
+ sai->cpu_dai_drv.symmetric_channels = 1;
1073
+ sai->cpu_dai_drv.symmetric_samplebits = 1;
8601074
8611075 if (of_find_property(np, "fsl,sai-synchronous-rx", NULL) &&
8621076 of_find_property(np, "fsl,sai-asynchronous", NULL)) {
....@@ -873,9 +1087,9 @@
8731087 /* Discard all settings for asynchronous mode */
8741088 sai->synchronous[RX] = false;
8751089 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;
1090
+ sai->cpu_dai_drv.symmetric_rates = 0;
1091
+ sai->cpu_dai_drv.symmetric_channels = 0;
1092
+ sai->cpu_dai_drv.symmetric_samplebits = 0;
8791093 }
8801094
8811095 if (of_find_property(np, "fsl,sai-mclk-direction-output", NULL) &&
....@@ -894,63 +1108,183 @@
8941108 MCLK_DIR(index));
8951109 }
8961110
897
- sai->dma_params_rx.addr = res->start + FSL_SAI_RDR;
898
- sai->dma_params_tx.addr = res->start + FSL_SAI_TDR;
1111
+ sai->dma_params_rx.addr = res->start + FSL_SAI_RDR0;
1112
+ sai->dma_params_tx.addr = res->start + FSL_SAI_TDR0;
8991113 sai->dma_params_rx.maxburst = FSL_SAI_MAXBURST_RX;
9001114 sai->dma_params_tx.maxburst = FSL_SAI_MAXBURST_TX;
9011115
9021116 platform_set_drvdata(pdev, sai);
9031117
904
- ret = devm_snd_soc_register_component(&pdev->dev, &fsl_component,
905
- &fsl_sai_dai, 1);
906
- if (ret)
907
- return ret;
1118
+ /* Get sai version */
1119
+ ret = fsl_sai_check_version(&pdev->dev);
1120
+ if (ret < 0)
1121
+ dev_warn(&pdev->dev, "Error reading SAI version: %d\n", ret);
9081122
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);
1123
+ /* Select MCLK direction */
1124
+ if (of_find_property(np, "fsl,sai-mclk-direction-output", NULL) &&
1125
+ sai->verid.major >= 3 && sai->verid.minor >= 1) {
1126
+ regmap_update_bits(sai->regmap, FSL_SAI_MCTL,
1127
+ FSL_SAI_MCTL_MCLK_EN, FSL_SAI_MCTL_MCLK_EN);
1128
+ }
1129
+
1130
+ pm_runtime_enable(&pdev->dev);
1131
+ regcache_cache_only(sai->regmap, true);
1132
+
1133
+ ret = devm_snd_soc_register_component(&pdev->dev, &fsl_component,
1134
+ &sai->cpu_dai_drv, 1);
1135
+ if (ret)
1136
+ goto err_pm_disable;
1137
+
1138
+ if (sai->soc_data->use_imx_pcm) {
1139
+ ret = imx_pcm_dma_init(pdev, IMX_SAI_DMABUF_SIZE);
1140
+ if (ret)
1141
+ goto err_pm_disable;
1142
+ } else {
1143
+ ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
1144
+ if (ret)
1145
+ goto err_pm_disable;
1146
+ }
1147
+
1148
+ return ret;
1149
+
1150
+err_pm_disable:
1151
+ pm_runtime_disable(&pdev->dev);
1152
+
1153
+ return ret;
9131154 }
9141155
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)
1156
+static int fsl_sai_remove(struct platform_device *pdev)
9251157 {
926
- struct fsl_sai *sai = dev_get_drvdata(dev);
927
-
928
- regcache_cache_only(sai->regmap, true);
929
- regcache_mark_dirty(sai->regmap);
1158
+ pm_runtime_disable(&pdev->dev);
9301159
9311160 return 0;
9321161 }
9331162
934
-static int fsl_sai_resume(struct device *dev)
1163
+static const struct fsl_sai_soc_data fsl_sai_vf610_data = {
1164
+ .use_imx_pcm = false,
1165
+ .use_edma = false,
1166
+ .fifo_depth = 32,
1167
+ .reg_offset = 0,
1168
+};
1169
+
1170
+static const struct fsl_sai_soc_data fsl_sai_imx6sx_data = {
1171
+ .use_imx_pcm = true,
1172
+ .use_edma = false,
1173
+ .fifo_depth = 32,
1174
+ .reg_offset = 0,
1175
+};
1176
+
1177
+static const struct fsl_sai_soc_data fsl_sai_imx7ulp_data = {
1178
+ .use_imx_pcm = true,
1179
+ .use_edma = false,
1180
+ .fifo_depth = 16,
1181
+ .reg_offset = 8,
1182
+};
1183
+
1184
+static const struct fsl_sai_soc_data fsl_sai_imx8mq_data = {
1185
+ .use_imx_pcm = true,
1186
+ .use_edma = false,
1187
+ .fifo_depth = 128,
1188
+ .reg_offset = 8,
1189
+};
1190
+
1191
+static const struct fsl_sai_soc_data fsl_sai_imx8qm_data = {
1192
+ .use_imx_pcm = true,
1193
+ .use_edma = true,
1194
+ .fifo_depth = 64,
1195
+ .reg_offset = 0,
1196
+};
1197
+
1198
+static const struct of_device_id fsl_sai_ids[] = {
1199
+ { .compatible = "fsl,vf610-sai", .data = &fsl_sai_vf610_data },
1200
+ { .compatible = "fsl,imx6sx-sai", .data = &fsl_sai_imx6sx_data },
1201
+ { .compatible = "fsl,imx6ul-sai", .data = &fsl_sai_imx6sx_data },
1202
+ { .compatible = "fsl,imx7ulp-sai", .data = &fsl_sai_imx7ulp_data },
1203
+ { .compatible = "fsl,imx8mq-sai", .data = &fsl_sai_imx8mq_data },
1204
+ { .compatible = "fsl,imx8qm-sai", .data = &fsl_sai_imx8qm_data },
1205
+ { /* sentinel */ }
1206
+};
1207
+MODULE_DEVICE_TABLE(of, fsl_sai_ids);
1208
+
1209
+#ifdef CONFIG_PM
1210
+static int fsl_sai_runtime_suspend(struct device *dev)
9351211 {
9361212 struct fsl_sai *sai = dev_get_drvdata(dev);
9371213
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);
1214
+ if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_CAPTURE))
1215
+ clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[0]]);
1216
+
1217
+ if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_PLAYBACK))
1218
+ clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[1]]);
1219
+
1220
+ clk_disable_unprepare(sai->bus_clk);
1221
+
1222
+ regcache_cache_only(sai->regmap, true);
1223
+
1224
+ return 0;
9451225 }
946
-#endif /* CONFIG_PM_SLEEP */
1226
+
1227
+static int fsl_sai_runtime_resume(struct device *dev)
1228
+{
1229
+ struct fsl_sai *sai = dev_get_drvdata(dev);
1230
+ unsigned int ofs = sai->soc_data->reg_offset;
1231
+ int ret;
1232
+
1233
+ ret = clk_prepare_enable(sai->bus_clk);
1234
+ if (ret) {
1235
+ dev_err(dev, "failed to enable bus clock: %d\n", ret);
1236
+ return ret;
1237
+ }
1238
+
1239
+ if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_PLAYBACK)) {
1240
+ ret = clk_prepare_enable(sai->mclk_clk[sai->mclk_id[1]]);
1241
+ if (ret)
1242
+ goto disable_bus_clk;
1243
+ }
1244
+
1245
+ if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_CAPTURE)) {
1246
+ ret = clk_prepare_enable(sai->mclk_clk[sai->mclk_id[0]]);
1247
+ if (ret)
1248
+ goto disable_tx_clk;
1249
+ }
1250
+
1251
+ regcache_cache_only(sai->regmap, false);
1252
+ regcache_mark_dirty(sai->regmap);
1253
+ regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), FSL_SAI_CSR_SR);
1254
+ regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), FSL_SAI_CSR_SR);
1255
+ usleep_range(1000, 2000);
1256
+ regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), 0);
1257
+ regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), 0);
1258
+
1259
+ ret = regcache_sync(sai->regmap);
1260
+ if (ret)
1261
+ goto disable_rx_clk;
1262
+
1263
+ return 0;
1264
+
1265
+disable_rx_clk:
1266
+ if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_CAPTURE))
1267
+ clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[0]]);
1268
+disable_tx_clk:
1269
+ if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_PLAYBACK))
1270
+ clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[1]]);
1271
+disable_bus_clk:
1272
+ clk_disable_unprepare(sai->bus_clk);
1273
+
1274
+ return ret;
1275
+}
1276
+#endif /* CONFIG_PM */
9471277
9481278 static const struct dev_pm_ops fsl_sai_pm_ops = {
949
- SET_SYSTEM_SLEEP_PM_OPS(fsl_sai_suspend, fsl_sai_resume)
1279
+ SET_RUNTIME_PM_OPS(fsl_sai_runtime_suspend,
1280
+ fsl_sai_runtime_resume, NULL)
1281
+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
1282
+ pm_runtime_force_resume)
9501283 };
9511284
9521285 static struct platform_driver fsl_sai_driver = {
9531286 .probe = fsl_sai_probe,
1287
+ .remove = fsl_sai_remove,
9541288 .driver = {
9551289 .name = "fsl-sai",
9561290 .pm = &fsl_sai_pm_ops,