diff options
Diffstat (limited to 'sound/soc/davinci/davinci-mcasp.c')
-rw-r--r-- | sound/soc/davinci/davinci-mcasp.c | 82 |
1 files changed, 59 insertions, 23 deletions
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index c2e67f1f194c..aeb3a6627d6a 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c | |||
@@ -235,6 +235,8 @@ | |||
235 | #define DISMOD (val)(val<<2) | 235 | #define DISMOD (val)(val<<2) |
236 | #define TXSTATE BIT(4) | 236 | #define TXSTATE BIT(4) |
237 | #define RXSTATE BIT(5) | 237 | #define RXSTATE BIT(5) |
238 | #define SRMOD_MASK 3 | ||
239 | #define SRMOD_INACTIVE 0 | ||
238 | 240 | ||
239 | /* | 241 | /* |
240 | * DAVINCI_MCASP_LBCTL_REG - Loop Back Control Register Bits | 242 | * DAVINCI_MCASP_LBCTL_REG - Loop Back Control Register Bits |
@@ -643,26 +645,33 @@ static int davinci_config_channel_size(struct davinci_audio_dev *dev, | |||
643 | /* mapping of the XSSZ bit-field as described in the datasheet */ | 645 | /* mapping of the XSSZ bit-field as described in the datasheet */ |
644 | fmt = (word_length >> 1) - 1; | 646 | fmt = (word_length >> 1) - 1; |
645 | 647 | ||
646 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, | 648 | if (dev->op_mode != DAVINCI_MCASP_DIT_MODE) { |
647 | RXSSZ(fmt), RXSSZ(0x0F)); | 649 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, |
648 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, | 650 | RXSSZ(fmt), RXSSZ(0x0F)); |
649 | TXSSZ(fmt), TXSSZ(0x0F)); | 651 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, |
650 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXROT(rotate), | 652 | TXSSZ(fmt), TXSSZ(0x0F)); |
651 | TXROT(7)); | 653 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, |
652 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, RXROT(rotate), | 654 | TXROT(rotate), TXROT(7)); |
653 | RXROT(7)); | 655 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, |
656 | RXROT(rotate), RXROT(7)); | ||
657 | mcasp_set_reg(dev->base + DAVINCI_MCASP_RXMASK_REG, | ||
658 | mask); | ||
659 | } | ||
660 | |||
654 | mcasp_set_reg(dev->base + DAVINCI_MCASP_TXMASK_REG, mask); | 661 | mcasp_set_reg(dev->base + DAVINCI_MCASP_TXMASK_REG, mask); |
655 | mcasp_set_reg(dev->base + DAVINCI_MCASP_RXMASK_REG, mask); | ||
656 | 662 | ||
657 | return 0; | 663 | return 0; |
658 | } | 664 | } |
659 | 665 | ||
660 | static void davinci_hw_common_param(struct davinci_audio_dev *dev, int stream) | 666 | static int davinci_hw_common_param(struct davinci_audio_dev *dev, int stream, |
667 | int channels) | ||
661 | { | 668 | { |
662 | int i; | 669 | int i; |
663 | u8 tx_ser = 0; | 670 | u8 tx_ser = 0; |
664 | u8 rx_ser = 0; | 671 | u8 rx_ser = 0; |
665 | 672 | u8 ser; | |
673 | u8 slots = dev->tdm_slots; | ||
674 | u8 max_active_serializers = (channels + slots - 1) / slots; | ||
666 | /* Default configuration */ | 675 | /* Default configuration */ |
667 | mcasp_set_bits(dev->base + DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT); | 676 | mcasp_set_bits(dev->base + DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT); |
668 | 677 | ||
@@ -682,17 +691,33 @@ static void davinci_hw_common_param(struct davinci_audio_dev *dev, int stream) | |||
682 | for (i = 0; i < dev->num_serializer; i++) { | 691 | for (i = 0; i < dev->num_serializer; i++) { |
683 | mcasp_set_bits(dev->base + DAVINCI_MCASP_XRSRCTL_REG(i), | 692 | mcasp_set_bits(dev->base + DAVINCI_MCASP_XRSRCTL_REG(i), |
684 | dev->serial_dir[i]); | 693 | dev->serial_dir[i]); |
685 | if (dev->serial_dir[i] == TX_MODE) { | 694 | if (dev->serial_dir[i] == TX_MODE && |
695 | tx_ser < max_active_serializers) { | ||
686 | mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG, | 696 | mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG, |
687 | AXR(i)); | 697 | AXR(i)); |
688 | tx_ser++; | 698 | tx_ser++; |
689 | } else if (dev->serial_dir[i] == RX_MODE) { | 699 | } else if (dev->serial_dir[i] == RX_MODE && |
700 | rx_ser < max_active_serializers) { | ||
690 | mcasp_clr_bits(dev->base + DAVINCI_MCASP_PDIR_REG, | 701 | mcasp_clr_bits(dev->base + DAVINCI_MCASP_PDIR_REG, |
691 | AXR(i)); | 702 | AXR(i)); |
692 | rx_ser++; | 703 | rx_ser++; |
704 | } else { | ||
705 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_XRSRCTL_REG(i), | ||
706 | SRMOD_INACTIVE, SRMOD_MASK); | ||
693 | } | 707 | } |
694 | } | 708 | } |
695 | 709 | ||
710 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
711 | ser = tx_ser; | ||
712 | else | ||
713 | ser = rx_ser; | ||
714 | |||
715 | if (ser < max_active_serializers) { | ||
716 | dev_warn(dev->dev, "stream has more channels (%d) than are " | ||
717 | "enabled in mcasp (%d)\n", channels, ser * slots); | ||
718 | return -EINVAL; | ||
719 | } | ||
720 | |||
696 | if (dev->txnumevt && stream == SNDRV_PCM_STREAM_PLAYBACK) { | 721 | if (dev->txnumevt && stream == SNDRV_PCM_STREAM_PLAYBACK) { |
697 | if (dev->txnumevt * tx_ser > 64) | 722 | if (dev->txnumevt * tx_ser > 64) |
698 | dev->txnumevt = 1; | 723 | dev->txnumevt = 1; |
@@ -729,6 +754,8 @@ static void davinci_hw_common_param(struct davinci_audio_dev *dev, int stream) | |||
729 | ((dev->rxnumevt * rx_ser) << 8), NUMEVT_MASK); | 754 | ((dev->rxnumevt * rx_ser) << 8), NUMEVT_MASK); |
730 | } | 755 | } |
731 | } | 756 | } |
757 | |||
758 | return 0; | ||
732 | } | 759 | } |
733 | 760 | ||
734 | static void davinci_hw_param(struct davinci_audio_dev *dev, int stream) | 761 | static void davinci_hw_param(struct davinci_audio_dev *dev, int stream) |
@@ -772,12 +799,6 @@ static void davinci_hw_param(struct davinci_audio_dev *dev, int stream) | |||
772 | /* S/PDIF */ | 799 | /* S/PDIF */ |
773 | static void davinci_hw_dit_param(struct davinci_audio_dev *dev) | 800 | static void davinci_hw_dit_param(struct davinci_audio_dev *dev) |
774 | { | 801 | { |
775 | /* Set the PDIR for Serialiser as output */ | ||
776 | mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG, AFSX); | ||
777 | |||
778 | /* TXMASK for 24 bits */ | ||
779 | mcasp_set_reg(dev->base + DAVINCI_MCASP_TXMASK_REG, 0x00FFFFFF); | ||
780 | |||
781 | /* Set the TX format : 24 bit right rotation, 32 bit slot, Pad 0 | 802 | /* Set the TX format : 24 bit right rotation, 32 bit slot, Pad 0 |
782 | and LSB first */ | 803 | and LSB first */ |
783 | mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, | 804 | mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, |
@@ -812,8 +833,14 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, | |||
812 | &dev->dma_params[substream->stream]; | 833 | &dev->dma_params[substream->stream]; |
813 | int word_length; | 834 | int word_length; |
814 | u8 fifo_level; | 835 | u8 fifo_level; |
836 | u8 slots = dev->tdm_slots; | ||
837 | int channels; | ||
838 | struct snd_interval *pcm_channels = hw_param_interval(params, | ||
839 | SNDRV_PCM_HW_PARAM_CHANNELS); | ||
840 | channels = pcm_channels->min; | ||
815 | 841 | ||
816 | davinci_hw_common_param(dev, substream->stream); | 842 | if (davinci_hw_common_param(dev, substream->stream, channels) == -EINVAL) |
843 | return -EINVAL; | ||
817 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 844 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
818 | fifo_level = dev->txnumevt; | 845 | fifo_level = dev->txnumevt; |
819 | else | 846 | else |
@@ -862,6 +889,7 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, | |||
862 | dma_params->acnt = dma_params->data_type; | 889 | dma_params->acnt = dma_params->data_type; |
863 | 890 | ||
864 | dma_params->fifo_level = fifo_level; | 891 | dma_params->fifo_level = fifo_level; |
892 | dma_params->active_serializers = (channels + slots - 1) / slots; | ||
865 | davinci_config_channel_size(dev, word_length); | 893 | davinci_config_channel_size(dev, word_length); |
866 | 894 | ||
867 | return 0; | 895 | return 0; |
@@ -936,13 +964,13 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = { | |||
936 | .name = "davinci-mcasp.0", | 964 | .name = "davinci-mcasp.0", |
937 | .playback = { | 965 | .playback = { |
938 | .channels_min = 2, | 966 | .channels_min = 2, |
939 | .channels_max = 2, | 967 | .channels_max = 32 * 16, |
940 | .rates = DAVINCI_MCASP_RATES, | 968 | .rates = DAVINCI_MCASP_RATES, |
941 | .formats = DAVINCI_MCASP_PCM_FMTS, | 969 | .formats = DAVINCI_MCASP_PCM_FMTS, |
942 | }, | 970 | }, |
943 | .capture = { | 971 | .capture = { |
944 | .channels_min = 2, | 972 | .channels_min = 2, |
945 | .channels_max = 2, | 973 | .channels_max = 32 * 16, |
946 | .rates = DAVINCI_MCASP_RATES, | 974 | .rates = DAVINCI_MCASP_RATES, |
947 | .formats = DAVINCI_MCASP_PCM_FMTS, | 975 | .formats = DAVINCI_MCASP_PCM_FMTS, |
948 | }, | 976 | }, |
@@ -1019,8 +1047,16 @@ static struct snd_platform_data *davinci_mcasp_set_pdata_from_of( | |||
1019 | pdata->op_mode = val; | 1047 | pdata->op_mode = val; |
1020 | 1048 | ||
1021 | ret = of_property_read_u32(np, "tdm-slots", &val); | 1049 | ret = of_property_read_u32(np, "tdm-slots", &val); |
1022 | if (ret >= 0) | 1050 | if (ret >= 0) { |
1051 | if (val < 2 || val > 32) { | ||
1052 | dev_err(&pdev->dev, | ||
1053 | "tdm-slots must be in rage [2-32]\n"); | ||
1054 | ret = -EINVAL; | ||
1055 | goto nodata; | ||
1056 | } | ||
1057 | |||
1023 | pdata->tdm_slots = val; | 1058 | pdata->tdm_slots = val; |
1059 | } | ||
1024 | 1060 | ||
1025 | ret = of_property_read_u32(np, "num-serializer", &val); | 1061 | ret = of_property_read_u32(np, "num-serializer", &val); |
1026 | if (ret >= 0) | 1062 | if (ret >= 0) |