diff options
author | Michał Mirosław <mirq-linux@rere.qmqm.pl> | 2019-08-24 16:26:53 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2019-08-27 15:40:43 -0400 |
commit | db8e3e2091c3ccc4e1dde0f78b3111301cf129e9 (patch) | |
tree | a4b7f564ac00ba36aea62338cd759847cf71104a /sound | |
parent | 18291410557fb860706d1889505cc15d6e31d790 (diff) |
ASoC: atmel_ssc_dai: rework DAI format configuration
Rework DAI format calculation in preparation for adding more formats
later. As a side-effect this enables all CBM/CBS x CFM/CFS combinations
for supported formats. (Note: the additional modes are not tested.)
Note: this changes FSEDGE to POSITIVE for I2S CBM_CFS mode as the TXSYN
interrupt is not used anyway.
Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Link: https://lore.kernel.org/r/f5949b0326fdcdca072f3ed03f77de9e207631cd.1566677788.git.mirq-linux@rere.qmqm.pl
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/atmel/atmel_ssc_dai.c | 288 |
1 files changed, 81 insertions, 207 deletions
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index 6f89483ac88c..7dc6ec9b8c7a 100644 --- a/sound/soc/atmel/atmel_ssc_dai.c +++ b/sound/soc/atmel/atmel_ssc_dai.c | |||
@@ -471,7 +471,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | |||
471 | int dir, channels, bits; | 471 | int dir, channels, bits; |
472 | u32 tfmr, rfmr, tcmr, rcmr; | 472 | u32 tfmr, rfmr, tcmr, rcmr; |
473 | int ret; | 473 | int ret; |
474 | int fslen, fslen_ext; | 474 | int fslen, fslen_ext, fs_osync, fs_edge; |
475 | u32 cmr_div; | 475 | u32 cmr_div; |
476 | u32 tcmr_period; | 476 | u32 tcmr_period; |
477 | u32 rcmr_period; | 477 | u32 rcmr_period; |
@@ -558,233 +558,107 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | |||
558 | /* | 558 | /* |
559 | * Compute SSC register settings. | 559 | * Compute SSC register settings. |
560 | */ | 560 | */ |
561 | switch (ssc_p->daifmt | ||
562 | & (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_MASTER_MASK)) { | ||
563 | 561 | ||
564 | case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS: | 562 | fslen_ext = (bits - 1) / 16; |
563 | fslen = (bits - 1) % 16; | ||
564 | |||
565 | switch (ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
566 | |||
567 | case SND_SOC_DAIFMT_I2S: | ||
568 | fs_osync = SSC_FSOS_NEGATIVE; | ||
569 | fs_edge = SSC_START_FALLING_RF; | ||
570 | |||
571 | rcmr = SSC_BF(RCMR_STTDLY, 1); | ||
572 | tcmr = SSC_BF(TCMR_STTDLY, 1); | ||
573 | |||
574 | break; | ||
575 | |||
576 | case SND_SOC_DAIFMT_DSP_A: | ||
565 | /* | 577 | /* |
566 | * I2S format, SSC provides BCLK and LRC clocks. | 578 | * DSP/PCM Mode A format |
567 | * | 579 | * |
568 | * The SSC transmit and receive clocks are generated | 580 | * Data is transferred on first BCLK after LRC pulse rising |
569 | * from the MCK divider, and the BCLK signal | 581 | * edge.If stereo, the right channel data is contiguous with |
570 | * is output on the SSC TK line. | 582 | * the left channel data. |
571 | */ | 583 | */ |
584 | fs_osync = SSC_FSOS_POSITIVE; | ||
585 | fs_edge = SSC_START_RISING_RF; | ||
586 | fslen = fslen_ext = 0; | ||
572 | 587 | ||
573 | if (bits > 16 && !ssc->pdata->has_fslen_ext) { | 588 | rcmr = SSC_BF(RCMR_STTDLY, 1); |
574 | dev_err(dai->dev, | 589 | tcmr = SSC_BF(TCMR_STTDLY, 1); |
575 | "sample size %d is too large for SSC device\n", | ||
576 | bits); | ||
577 | return -EINVAL; | ||
578 | } | ||
579 | 590 | ||
580 | fslen_ext = (bits - 1) / 16; | ||
581 | fslen = (bits - 1) % 16; | ||
582 | |||
583 | rcmr = SSC_BF(RCMR_PERIOD, rcmr_period) | ||
584 | | SSC_BF(RCMR_STTDLY, START_DELAY) | ||
585 | | SSC_BF(RCMR_START, SSC_START_FALLING_RF) | ||
586 | | SSC_BF(RCMR_CKI, SSC_CKI_RISING) | ||
587 | | SSC_BF(RCMR_CKO, SSC_CKO_NONE) | ||
588 | | SSC_BF(RCMR_CKS, SSC_CKS_DIV); | ||
589 | |||
590 | rfmr = SSC_BF(RFMR_FSLEN_EXT, fslen_ext) | ||
591 | | SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | ||
592 | | SSC_BF(RFMR_FSOS, SSC_FSOS_NEGATIVE) | ||
593 | | SSC_BF(RFMR_FSLEN, fslen) | ||
594 | | SSC_BF(RFMR_DATNB, (channels - 1)) | ||
595 | | SSC_BIT(RFMR_MSBF) | ||
596 | | SSC_BF(RFMR_LOOP, 0) | ||
597 | | SSC_BF(RFMR_DATLEN, (bits - 1)); | ||
598 | |||
599 | tcmr = SSC_BF(TCMR_PERIOD, tcmr_period) | ||
600 | | SSC_BF(TCMR_STTDLY, START_DELAY) | ||
601 | | SSC_BF(TCMR_START, SSC_START_FALLING_RF) | ||
602 | | SSC_BF(TCMR_CKI, SSC_CKI_FALLING) | ||
603 | | SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS) | ||
604 | | SSC_BF(TCMR_CKS, SSC_CKS_DIV); | ||
605 | |||
606 | tfmr = SSC_BF(TFMR_FSLEN_EXT, fslen_ext) | ||
607 | | SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | ||
608 | | SSC_BF(TFMR_FSDEN, 0) | ||
609 | | SSC_BF(TFMR_FSOS, SSC_FSOS_NEGATIVE) | ||
610 | | SSC_BF(TFMR_FSLEN, fslen) | ||
611 | | SSC_BF(TFMR_DATNB, (channels - 1)) | ||
612 | | SSC_BIT(TFMR_MSBF) | ||
613 | | SSC_BF(TFMR_DATDEF, 0) | ||
614 | | SSC_BF(TFMR_DATLEN, (bits - 1)); | ||
615 | break; | 591 | break; |
616 | 592 | ||
617 | case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM: | 593 | default: |
618 | /* I2S format, CODEC supplies BCLK and LRC clocks. */ | 594 | printk(KERN_WARNING "atmel_ssc_dai: unsupported DAI format 0x%x\n", |
619 | rcmr = SSC_BF(RCMR_PERIOD, 0) | 595 | ssc_p->daifmt); |
620 | | SSC_BF(RCMR_STTDLY, START_DELAY) | 596 | return -EINVAL; |
621 | | SSC_BF(RCMR_START, SSC_START_FALLING_RF) | 597 | } |
622 | | SSC_BF(RCMR_CKI, SSC_CKI_RISING) | ||
623 | | SSC_BF(RCMR_CKO, SSC_CKO_NONE) | ||
624 | | SSC_BF(RCMR_CKS, ssc->clk_from_rk_pin ? | ||
625 | SSC_CKS_PIN : SSC_CKS_CLOCK); | ||
626 | |||
627 | rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | ||
628 | | SSC_BF(RFMR_FSOS, SSC_FSOS_NONE) | ||
629 | | SSC_BF(RFMR_FSLEN, 0) | ||
630 | | SSC_BF(RFMR_DATNB, (channels - 1)) | ||
631 | | SSC_BIT(RFMR_MSBF) | ||
632 | | SSC_BF(RFMR_LOOP, 0) | ||
633 | | SSC_BF(RFMR_DATLEN, (bits - 1)); | ||
634 | |||
635 | tcmr = SSC_BF(TCMR_PERIOD, 0) | ||
636 | | SSC_BF(TCMR_STTDLY, START_DELAY) | ||
637 | | SSC_BF(TCMR_START, SSC_START_FALLING_RF) | ||
638 | | SSC_BF(TCMR_CKI, SSC_CKI_FALLING) | ||
639 | | SSC_BF(TCMR_CKO, SSC_CKO_NONE) | ||
640 | | SSC_BF(TCMR_CKS, ssc->clk_from_rk_pin ? | ||
641 | SSC_CKS_CLOCK : SSC_CKS_PIN); | ||
642 | |||
643 | tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | ||
644 | | SSC_BF(TFMR_FSDEN, 0) | ||
645 | | SSC_BF(TFMR_FSOS, SSC_FSOS_NONE) | ||
646 | | SSC_BF(TFMR_FSLEN, 0) | ||
647 | | SSC_BF(TFMR_DATNB, (channels - 1)) | ||
648 | | SSC_BIT(TFMR_MSBF) | ||
649 | | SSC_BF(TFMR_DATDEF, 0) | ||
650 | | SSC_BF(TFMR_DATLEN, (bits - 1)); | ||
651 | break; | ||
652 | 598 | ||
653 | case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFS: | 599 | if (!atmel_ssc_cfs(ssc_p)) { |
654 | /* I2S format, CODEC supplies BCLK, SSC supplies LRCLK. */ | 600 | fslen = fslen_ext = 0; |
655 | if (bits > 16 && !ssc->pdata->has_fslen_ext) { | 601 | rcmr_period = tcmr_period = 0; |
656 | dev_err(dai->dev, | 602 | fs_osync = SSC_FSOS_NONE; |
657 | "sample size %d is too large for SSC device\n", | 603 | } |
658 | bits); | ||
659 | return -EINVAL; | ||
660 | } | ||
661 | 604 | ||
662 | fslen_ext = (bits - 1) / 16; | 605 | rcmr |= SSC_BF(RCMR_START, fs_edge); |
663 | fslen = (bits - 1) % 16; | 606 | tcmr |= SSC_BF(TCMR_START, fs_edge); |
664 | |||
665 | rcmr = SSC_BF(RCMR_PERIOD, rcmr_period) | ||
666 | | SSC_BF(RCMR_STTDLY, START_DELAY) | ||
667 | | SSC_BF(RCMR_START, SSC_START_FALLING_RF) | ||
668 | | SSC_BF(RCMR_CKI, SSC_CKI_RISING) | ||
669 | | SSC_BF(RCMR_CKO, SSC_CKO_NONE) | ||
670 | | SSC_BF(RCMR_CKS, ssc->clk_from_rk_pin ? | ||
671 | SSC_CKS_PIN : SSC_CKS_CLOCK); | ||
672 | |||
673 | rfmr = SSC_BF(RFMR_FSLEN_EXT, fslen_ext) | ||
674 | | SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | ||
675 | | SSC_BF(RFMR_FSOS, SSC_FSOS_NEGATIVE) | ||
676 | | SSC_BF(RFMR_FSLEN, fslen) | ||
677 | | SSC_BF(RFMR_DATNB, (channels - 1)) | ||
678 | | SSC_BIT(RFMR_MSBF) | ||
679 | | SSC_BF(RFMR_LOOP, 0) | ||
680 | | SSC_BF(RFMR_DATLEN, (bits - 1)); | ||
681 | |||
682 | tcmr = SSC_BF(TCMR_PERIOD, tcmr_period) | ||
683 | | SSC_BF(TCMR_STTDLY, START_DELAY) | ||
684 | | SSC_BF(TCMR_START, SSC_START_FALLING_RF) | ||
685 | | SSC_BF(TCMR_CKI, SSC_CKI_FALLING) | ||
686 | | SSC_BF(TCMR_CKO, SSC_CKO_NONE) | ||
687 | | SSC_BF(TCMR_CKS, ssc->clk_from_rk_pin ? | ||
688 | SSC_CKS_CLOCK : SSC_CKS_PIN); | ||
689 | |||
690 | tfmr = SSC_BF(TFMR_FSLEN_EXT, fslen_ext) | ||
691 | | SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_NEGATIVE) | ||
692 | | SSC_BF(TFMR_FSDEN, 0) | ||
693 | | SSC_BF(TFMR_FSOS, SSC_FSOS_NEGATIVE) | ||
694 | | SSC_BF(TFMR_FSLEN, fslen) | ||
695 | | SSC_BF(TFMR_DATNB, (channels - 1)) | ||
696 | | SSC_BIT(TFMR_MSBF) | ||
697 | | SSC_BF(TFMR_DATDEF, 0) | ||
698 | | SSC_BF(TFMR_DATLEN, (bits - 1)); | ||
699 | break; | ||
700 | 607 | ||
701 | case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS: | 608 | if (atmel_ssc_cbs(ssc_p)) { |
702 | /* | 609 | /* |
703 | * DSP/PCM Mode A format, SSC provides BCLK and LRC clocks. | 610 | * SSC provides BCLK |
704 | * | 611 | * |
705 | * The SSC transmit and receive clocks are generated from the | 612 | * The SSC transmit and receive clocks are generated from the |
706 | * MCK divider, and the BCLK signal is output | 613 | * MCK divider, and the BCLK signal is output |
707 | * on the SSC TK line. | 614 | * on the SSC TK line. |
708 | */ | 615 | */ |
709 | rcmr = SSC_BF(RCMR_PERIOD, rcmr_period) | 616 | rcmr |= SSC_BF(RCMR_CKS, SSC_CKS_DIV) |
710 | | SSC_BF(RCMR_STTDLY, 1) | 617 | | SSC_BF(RCMR_CKO, SSC_CKO_NONE); |
711 | | SSC_BF(RCMR_START, SSC_START_RISING_RF) | ||
712 | | SSC_BF(RCMR_CKI, SSC_CKI_RISING) | ||
713 | | SSC_BF(RCMR_CKO, SSC_CKO_NONE) | ||
714 | | SSC_BF(RCMR_CKS, SSC_CKS_DIV); | ||
715 | |||
716 | rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | ||
717 | | SSC_BF(RFMR_FSOS, SSC_FSOS_POSITIVE) | ||
718 | | SSC_BF(RFMR_FSLEN, 0) | ||
719 | | SSC_BF(RFMR_DATNB, (channels - 1)) | ||
720 | | SSC_BIT(RFMR_MSBF) | ||
721 | | SSC_BF(RFMR_LOOP, 0) | ||
722 | | SSC_BF(RFMR_DATLEN, (bits - 1)); | ||
723 | |||
724 | tcmr = SSC_BF(TCMR_PERIOD, tcmr_period) | ||
725 | | SSC_BF(TCMR_STTDLY, 1) | ||
726 | | SSC_BF(TCMR_START, SSC_START_RISING_RF) | ||
727 | | SSC_BF(TCMR_CKI, SSC_CKI_FALLING) | ||
728 | | SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS) | ||
729 | | SSC_BF(TCMR_CKS, SSC_CKS_DIV); | ||
730 | |||
731 | tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | ||
732 | | SSC_BF(TFMR_FSDEN, 0) | ||
733 | | SSC_BF(TFMR_FSOS, SSC_FSOS_POSITIVE) | ||
734 | | SSC_BF(TFMR_FSLEN, 0) | ||
735 | | SSC_BF(TFMR_DATNB, (channels - 1)) | ||
736 | | SSC_BIT(TFMR_MSBF) | ||
737 | | SSC_BF(TFMR_DATDEF, 0) | ||
738 | | SSC_BF(TFMR_DATLEN, (bits - 1)); | ||
739 | break; | ||
740 | 618 | ||
741 | case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM: | 619 | tcmr |= SSC_BF(TCMR_CKS, SSC_CKS_DIV) |
742 | /* | 620 | | SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS); |
743 | * DSP/PCM Mode A format, CODEC supplies BCLK and LRC clocks. | 621 | } else { |
744 | * | 622 | rcmr |= SSC_BF(RCMR_CKS, ssc->clk_from_rk_pin ? |
745 | * Data is transferred on first BCLK after LRC pulse rising | 623 | SSC_CKS_PIN : SSC_CKS_CLOCK) |
746 | * edge.If stereo, the right channel data is contiguous with | 624 | | SSC_BF(RCMR_CKO, SSC_CKO_NONE); |
747 | * the left channel data. | ||
748 | */ | ||
749 | rcmr = SSC_BF(RCMR_PERIOD, 0) | ||
750 | | SSC_BF(RCMR_STTDLY, START_DELAY) | ||
751 | | SSC_BF(RCMR_START, SSC_START_RISING_RF) | ||
752 | | SSC_BF(RCMR_CKI, SSC_CKI_RISING) | ||
753 | | SSC_BF(RCMR_CKO, SSC_CKO_NONE) | ||
754 | | SSC_BF(RCMR_CKS, ssc->clk_from_rk_pin ? | ||
755 | SSC_CKS_PIN : SSC_CKS_CLOCK); | ||
756 | |||
757 | rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | ||
758 | | SSC_BF(RFMR_FSOS, SSC_FSOS_NONE) | ||
759 | | SSC_BF(RFMR_FSLEN, 0) | ||
760 | | SSC_BF(RFMR_DATNB, (channels - 1)) | ||
761 | | SSC_BIT(RFMR_MSBF) | ||
762 | | SSC_BF(RFMR_LOOP, 0) | ||
763 | | SSC_BF(RFMR_DATLEN, (bits - 1)); | ||
764 | |||
765 | tcmr = SSC_BF(TCMR_PERIOD, 0) | ||
766 | | SSC_BF(TCMR_STTDLY, START_DELAY) | ||
767 | | SSC_BF(TCMR_START, SSC_START_RISING_RF) | ||
768 | | SSC_BF(TCMR_CKI, SSC_CKI_FALLING) | ||
769 | | SSC_BF(TCMR_CKO, SSC_CKO_NONE) | ||
770 | | SSC_BF(RCMR_CKS, ssc->clk_from_rk_pin ? | ||
771 | SSC_CKS_CLOCK : SSC_CKS_PIN); | ||
772 | |||
773 | tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | ||
774 | | SSC_BF(TFMR_FSDEN, 0) | ||
775 | | SSC_BF(TFMR_FSOS, SSC_FSOS_NONE) | ||
776 | | SSC_BF(TFMR_FSLEN, 0) | ||
777 | | SSC_BF(TFMR_DATNB, (channels - 1)) | ||
778 | | SSC_BIT(TFMR_MSBF) | ||
779 | | SSC_BF(TFMR_DATDEF, 0) | ||
780 | | SSC_BF(TFMR_DATLEN, (bits - 1)); | ||
781 | break; | ||
782 | 625 | ||
783 | default: | 626 | tcmr |= SSC_BF(TCMR_CKS, ssc->clk_from_rk_pin ? |
784 | printk(KERN_WARNING "atmel_ssc_dai: unsupported DAI format 0x%x\n", | 627 | SSC_CKS_CLOCK : SSC_CKS_PIN) |
785 | ssc_p->daifmt); | 628 | | SSC_BF(TCMR_CKO, SSC_CKO_NONE); |
629 | } | ||
630 | |||
631 | rcmr |= SSC_BF(RCMR_PERIOD, rcmr_period) | ||
632 | | SSC_BF(RCMR_CKI, SSC_CKI_RISING); | ||
633 | |||
634 | tcmr |= SSC_BF(TCMR_PERIOD, tcmr_period) | ||
635 | | SSC_BF(TCMR_CKI, SSC_CKI_FALLING); | ||
636 | |||
637 | rfmr = SSC_BF(RFMR_FSLEN_EXT, fslen_ext) | ||
638 | | SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | ||
639 | | SSC_BF(RFMR_FSOS, fs_osync) | ||
640 | | SSC_BF(RFMR_FSLEN, fslen) | ||
641 | | SSC_BF(RFMR_DATNB, (channels - 1)) | ||
642 | | SSC_BIT(RFMR_MSBF) | ||
643 | | SSC_BF(RFMR_LOOP, 0) | ||
644 | | SSC_BF(RFMR_DATLEN, (bits - 1)); | ||
645 | |||
646 | tfmr = SSC_BF(TFMR_FSLEN_EXT, fslen_ext) | ||
647 | | SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | ||
648 | | SSC_BF(TFMR_FSDEN, 0) | ||
649 | | SSC_BF(TFMR_FSOS, fs_osync) | ||
650 | | SSC_BF(TFMR_FSLEN, fslen) | ||
651 | | SSC_BF(TFMR_DATNB, (channels - 1)) | ||
652 | | SSC_BIT(TFMR_MSBF) | ||
653 | | SSC_BF(TFMR_DATDEF, 0) | ||
654 | | SSC_BF(TFMR_DATLEN, (bits - 1)); | ||
655 | |||
656 | if (fslen_ext && !ssc->pdata->has_fslen_ext) { | ||
657 | dev_err(dai->dev, "sample size %d is too large for SSC device\n", | ||
658 | bits); | ||
786 | return -EINVAL; | 659 | return -EINVAL; |
787 | } | 660 | } |
661 | |||
788 | pr_debug("atmel_ssc_hw_params: " | 662 | pr_debug("atmel_ssc_hw_params: " |
789 | "RCMR=%08x RFMR=%08x TCMR=%08x TFMR=%08x\n", | 663 | "RCMR=%08x RFMR=%08x TCMR=%08x TFMR=%08x\n", |
790 | rcmr, rfmr, tcmr, tfmr); | 664 | rcmr, rfmr, tcmr, tfmr); |