Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ASoC: ti: davinci-mcasp: Add asynchronous mode support

McASP has dedicated clock & frame sync registers for both transmit
and receive. Currently McASP driver only supports synchronous behavior and
couples both TX & RX settings.

Add logic that enables asynchronous mode via ti,async-mode property. In
async mode, playback & record can be done simultaneously with different
audio configurations (tdm slots, tdm width, audio bit depth).

Note the ability to have different tx/rx DSP formats (i2s, dsp_a, etc.),
while possible in hardware, remains to be a gap as it require changes
to the corresponding machine driver interface.

Existing IIS (sync mode) and DIT mode logic remains mostly unchanged.
Exceptions are IIS mode logic that previously assumed sync mode, which has
now been made aware of the distinction. And shared logic across all modes
also now checks for McASP tx/rx-specific driver attributes. Those
attributes have been populated according to the original extent, ensuring
no divergence in functionality.

Constraints no longer applicable for async mode are skipped.
Clock selection options have also been added to include rx/tx-only clk_ids,
exposing independent configuration via the machine driver as well.

Note that asynchronous mode is not applicable for McASP in DIT mode,
which is a transmitter-only mode to interface w/ self-clocking formats.

Signed-off-by: Sen Wang <sen@ti.com>
Acked-by: Peter Ujfalusi <peter.ujfalusi@gmail.com>
Tested-by: Paresh Bhagat <p-bhagat@ti.com>
Link: https://patch.msgid.link/20260203003703.2334443-5-sen@ti.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Sen Wang and committed by
Mark Brown
9db32708 016efcaa

+401 -101
+2 -1
include/linux/platform_data/davinci_asp.h
··· 59 59 bool i2s_accurate_sck; 60 60 61 61 /* McASP specific fields */ 62 - int tdm_slots; 62 + int tdm_slots_tx; 63 + int tdm_slots_rx; 63 64 u8 op_mode; 64 65 u8 dismod; 65 66 u8 num_serializer;
+389 -100
sound/soc/ti/davinci-mcasp.c
··· 71 71 struct davinci_mcasp_ruledata { 72 72 struct davinci_mcasp *mcasp; 73 73 int serializers; 74 + int stream; 74 75 }; 75 76 76 77 struct davinci_mcasp { ··· 89 88 bool missing_audio_param; 90 89 91 90 /* McASP specific data */ 92 - int tdm_slots; 91 + int tdm_slots_tx; 92 + int tdm_slots_rx; 93 93 u32 tdm_mask[2]; 94 - int slot_width; 94 + int slot_width_tx; 95 + int slot_width_rx; 95 96 u8 op_mode; 96 97 u8 dismod; 97 98 u8 num_serializer; 98 99 u8 *serial_dir; 99 100 u8 version; 100 - u8 bclk_div; 101 + u8 bclk_div_tx; 102 + u8 bclk_div_rx; 101 103 int streams; 102 104 u32 irq_request[2]; 103 105 104 - int sysclk_freq; 106 + unsigned int sysclk_freq_tx; 107 + unsigned int sysclk_freq_rx; 105 108 bool bclk_master; 106 - u32 auxclk_fs_ratio; 109 + bool async_mode; 110 + u32 auxclk_fs_ratio_tx; 111 + u32 auxclk_fs_ratio_rx; 107 112 108 113 unsigned long pdir; /* Pin direction bitfield */ 109 114 ··· 211 204 } 212 205 } 213 206 207 + static inline void mcasp_set_clk_pdir_stream(struct davinci_mcasp *mcasp, 208 + int stream, bool enable) 209 + { 210 + u32 bit, bit_end; 211 + 212 + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { 213 + bit = PIN_BIT_ACLKX; 214 + bit_end = PIN_BIT_AFSX + 1; 215 + } else { 216 + bit = PIN_BIT_ACLKR; 217 + bit_end = PIN_BIT_AFSR + 1; 218 + } 219 + 220 + for_each_set_bit_from(bit, &mcasp->pdir, bit_end) { 221 + if (enable) 222 + mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(bit)); 223 + else 224 + mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(bit)); 225 + } 226 + } 227 + 214 228 static inline void mcasp_set_axr_pdir(struct davinci_mcasp *mcasp, bool enable) 215 229 { 216 230 u32 bit; ··· 242 214 else 243 215 mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(bit)); 244 216 } 217 + } 218 + 219 + static inline int mcasp_get_tdm_slots(struct davinci_mcasp *mcasp, int stream) 220 + { 221 + return (stream == SNDRV_PCM_STREAM_PLAYBACK) ? 222 + mcasp->tdm_slots_tx : mcasp->tdm_slots_rx; 223 + } 224 + 225 + static inline int mcasp_get_slot_width(struct davinci_mcasp *mcasp, int stream) 226 + { 227 + return (stream == SNDRV_PCM_STREAM_PLAYBACK) ? 228 + mcasp->slot_width_tx : mcasp->slot_width_rx; 229 + } 230 + 231 + static inline unsigned int mcasp_get_sysclk_freq(struct davinci_mcasp *mcasp, int stream) 232 + { 233 + return (stream == SNDRV_PCM_STREAM_PLAYBACK) ? 234 + mcasp->sysclk_freq_tx : mcasp->sysclk_freq_rx; 235 + } 236 + 237 + static inline unsigned int mcasp_get_bclk_div(struct davinci_mcasp *mcasp, int stream) 238 + { 239 + return (stream == SNDRV_PCM_STREAM_PLAYBACK) ? 240 + mcasp->bclk_div_tx : mcasp->bclk_div_rx; 241 + } 242 + 243 + static inline unsigned int mcasp_get_auxclk_fs_ratio(struct davinci_mcasp *mcasp, int stream) 244 + { 245 + return (stream == SNDRV_PCM_STREAM_PLAYBACK) ? 246 + mcasp->auxclk_fs_ratio_tx : mcasp->auxclk_fs_ratio_rx; 245 247 } 246 248 247 249 static void mcasp_start_rx(struct davinci_mcasp *mcasp) ··· 289 231 /* 290 232 * When ASYNC == 0 the transmit and receive sections operate 291 233 * synchronously from the transmit clock and frame sync. We need to make 292 - * sure that the TX signlas are enabled when starting reception. 234 + * sure that the TX signals are enabled when starting reception, 235 + * when the McASP is the producer. 293 236 */ 294 237 if (mcasp_is_frame_producer(mcasp) && mcasp_is_synchronous(mcasp)) { 295 238 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST); 296 239 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST); 297 240 } 298 - mcasp_set_clk_pdir(mcasp, true); 241 + if (mcasp_is_synchronous(mcasp)) 242 + mcasp_set_clk_pdir(mcasp, true); 243 + else 244 + mcasp_set_clk_pdir_stream(mcasp, SNDRV_PCM_STREAM_CAPTURE, true); 299 245 300 246 /* Activate serializer(s) */ 301 247 mcasp_set_reg(mcasp, DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF); ··· 330 268 /* Start clocks */ 331 269 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST); 332 270 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST); 333 - mcasp_set_clk_pdir(mcasp, true); 271 + if (mcasp_is_synchronous(mcasp)) 272 + mcasp_set_clk_pdir(mcasp, true); 273 + else 274 + mcasp_set_clk_pdir_stream(mcasp, SNDRV_PCM_STREAM_PLAYBACK, true); 334 275 335 276 /* Activate serializer(s) */ 336 277 mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF); ··· 376 311 /* 377 312 * In synchronous mode stop the TX clocks if no other stream is 378 313 * running 314 + * Otherwise in async mode only stop RX clocks 379 315 */ 380 - if (!mcasp->streams) 316 + if (mcasp_is_synchronous(mcasp) && !mcasp->streams) 381 317 mcasp_set_clk_pdir(mcasp, false); 318 + else if (!mcasp_is_synchronous(mcasp)) 319 + mcasp_set_clk_pdir_stream(mcasp, SNDRV_PCM_STREAM_CAPTURE, false); 320 + /* 321 + * When McASP is the producer and operating in synchronous mode, 322 + * stop the transmit clocks if no other stream is running. As 323 + * tx & rx operate synchronously from the transmit clock. 324 + */ 382 325 if (mcasp_is_frame_producer(mcasp) && mcasp_is_synchronous(mcasp) && !mcasp->streams) 383 326 mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, 0); 384 327 ··· 411 338 /* 412 339 * In synchronous mode keep TX clocks running if the capture stream is 413 340 * still running. 341 + * Otherwise in async mode only stop TX clocks 414 342 */ 415 343 if (mcasp_is_frame_producer(mcasp) && mcasp_is_synchronous(mcasp) && mcasp->streams) 416 344 val = TXHCLKRST | TXCLKRST | TXFSRST; 417 - if (!mcasp->streams) 345 + if (mcasp_is_synchronous(mcasp) && !mcasp->streams) 418 346 mcasp_set_clk_pdir(mcasp, false); 347 + else if (!mcasp_is_synchronous(mcasp)) 348 + mcasp_set_clk_pdir_stream(mcasp, SNDRV_PCM_STREAM_PLAYBACK, false); 419 349 420 350 421 351 mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, val); ··· 702 626 AHCLKRDIV(div - 1), AHCLKRDIV_MASK); 703 627 break; 704 628 629 + case MCASP_CLKDIV_AUXCLK_TXONLY: /* MCLK divider for TX only */ 630 + mcasp_mod_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, 631 + AHCLKXDIV(div - 1), AHCLKXDIV_MASK); 632 + break; 633 + 634 + case MCASP_CLKDIV_AUXCLK_RXONLY: /* MCLK divider for RX only */ 635 + mcasp_mod_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, 636 + AHCLKRDIV(div - 1), AHCLKRDIV_MASK); 637 + break; 638 + 705 639 case MCASP_CLKDIV_BCLK: /* BCLK divider */ 706 640 mcasp_mod_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, 707 641 ACLKXDIV(div - 1), ACLKXDIV_MASK); 708 642 mcasp_mod_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, 709 643 ACLKRDIV(div - 1), ACLKRDIV_MASK); 644 + if (explicit) { 645 + mcasp->bclk_div_tx = div; 646 + mcasp->bclk_div_rx = div; 647 + } 648 + break; 649 + 650 + case MCASP_CLKDIV_BCLK_TXONLY: /* BCLK divider for TX only */ 651 + mcasp_mod_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, 652 + ACLKXDIV(div - 1), ACLKXDIV_MASK); 710 653 if (explicit) 711 - mcasp->bclk_div = div; 654 + mcasp->bclk_div_tx = div; 655 + break; 656 + 657 + case MCASP_CLKDIV_BCLK_RXONLY: /* BCLK divider for RX only */ 658 + mcasp_mod_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, 659 + ACLKRDIV(div - 1), ACLKRDIV_MASK); 660 + if (explicit) 661 + mcasp->bclk_div_rx = div; 712 662 break; 713 663 714 664 case MCASP_CLKDIV_BCLK_FS_RATIO: ··· 748 646 * tdm_slot width by dividing the ratio by the 749 647 * number of configured tdm slots. 750 648 */ 751 - mcasp->slot_width = div / mcasp->tdm_slots; 752 - if (div % mcasp->tdm_slots) 649 + mcasp->slot_width_tx = div / mcasp->tdm_slots_tx; 650 + if (div % mcasp->tdm_slots_tx) 753 651 dev_warn(mcasp->dev, 754 - "%s(): BCLK/LRCLK %d is not divisible by %d tdm slots", 755 - __func__, div, mcasp->tdm_slots); 652 + "%s(): BCLK/LRCLK %d is not divisible by %d tx tdm slots", 653 + __func__, div, mcasp->tdm_slots_tx); 654 + 655 + mcasp->slot_width_rx = div / mcasp->tdm_slots_rx; 656 + if (div % mcasp->tdm_slots_rx) 657 + dev_warn(mcasp->dev, 658 + "%s(): BCLK/LRCLK %d is not divisible by %d rx tdm slots", 659 + __func__, div, mcasp->tdm_slots_rx); 660 + break; 661 + 662 + case MCASP_CLKDIV_BCLK_FS_RATIO_TXONLY: 663 + mcasp->slot_width_tx = div / mcasp->tdm_slots_tx; 664 + if (div % mcasp->tdm_slots_tx) 665 + dev_warn(mcasp->dev, 666 + "%s(): BCLK/LRCLK %d is not divisible by %d tx tdm slots", 667 + __func__, div, mcasp->tdm_slots_tx); 668 + break; 669 + 670 + case MCASP_CLKDIV_BCLK_FS_RATIO_RXONLY: 671 + mcasp->slot_width_rx = div / mcasp->tdm_slots_rx; 672 + if (div % mcasp->tdm_slots_rx) 673 + dev_warn(mcasp->dev, 674 + "%s(): BCLK/LRCLK %d is not divisible by %d rx tdm slots", 675 + __func__, div, mcasp->tdm_slots_rx); 756 676 break; 757 677 758 678 default: ··· 808 684 mcasp_clr_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, 809 685 AHCLKRE); 810 686 clear_bit(PIN_BIT_AHCLKX, &mcasp->pdir); 687 + mcasp->sysclk_freq_tx = freq; 688 + mcasp->sysclk_freq_rx = freq; 689 + break; 690 + case MCASP_CLK_HCLK_AHCLK_TXONLY: 691 + mcasp_clr_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, 692 + AHCLKXE); 693 + clear_bit(PIN_BIT_AHCLKX, &mcasp->pdir); 694 + mcasp->sysclk_freq_tx = freq; 695 + break; 696 + case MCASP_CLK_HCLK_AHCLK_RXONLY: 697 + mcasp_clr_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, 698 + AHCLKRE); 699 + clear_bit(PIN_BIT_AHCLKR, &mcasp->pdir); 700 + mcasp->sysclk_freq_rx = freq; 811 701 break; 812 702 case MCASP_CLK_HCLK_AUXCLK: 813 703 mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, ··· 829 691 mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, 830 692 AHCLKRE); 831 693 set_bit(PIN_BIT_AHCLKX, &mcasp->pdir); 694 + mcasp->sysclk_freq_tx = freq; 695 + mcasp->sysclk_freq_rx = freq; 696 + break; 697 + case MCASP_CLK_HCLK_AUXCLK_TXONLY: 698 + mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, 699 + AHCLKXE); 700 + set_bit(PIN_BIT_AHCLKX, &mcasp->pdir); 701 + mcasp->sysclk_freq_tx = freq; 702 + break; 703 + case MCASP_CLK_HCLK_AUXCLK_RXONLY: 704 + mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, 705 + AHCLKRE); 706 + set_bit(PIN_BIT_AHCLKR, &mcasp->pdir); 707 + mcasp->sysclk_freq_rx = freq; 832 708 break; 833 709 default: 834 710 dev_err(mcasp->dev, "Invalid clk id: %d\n", clk_id); 835 711 goto out; 836 712 } 837 713 } else { 838 - /* Select AUXCLK as HCLK */ 839 - mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE); 840 - mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, AHCLKRE); 841 - set_bit(PIN_BIT_AHCLKX, &mcasp->pdir); 714 + /* McASP is clock master, select AUXCLK as HCLK */ 715 + switch (clk_id) { 716 + case MCASP_CLK_HCLK_AUXCLK_TXONLY: 717 + mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, 718 + AHCLKXE); 719 + set_bit(PIN_BIT_AHCLKX, &mcasp->pdir); 720 + mcasp->sysclk_freq_tx = freq; 721 + break; 722 + case MCASP_CLK_HCLK_AUXCLK_RXONLY: 723 + mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, 724 + AHCLKRE); 725 + set_bit(PIN_BIT_AHCLKR, &mcasp->pdir); 726 + mcasp->sysclk_freq_rx = freq; 727 + break; 728 + default: 729 + mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, 730 + AHCLKXE); 731 + mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, 732 + AHCLKRE); 733 + set_bit(PIN_BIT_AHCLKX, &mcasp->pdir); 734 + set_bit(PIN_BIT_AHCLKR, &mcasp->pdir); 735 + mcasp->sysclk_freq_tx = freq; 736 + mcasp->sysclk_freq_rx = freq; 737 + break; 738 + } 842 739 } 843 740 /* 844 741 * When AHCLK X/R is selected to be output it means that the HCLK is 845 742 * the same clock - coming via AUXCLK. 846 743 */ 847 - mcasp->sysclk_freq = freq; 848 744 out: 849 745 pm_runtime_put(mcasp->dev); 850 746 return 0; ··· 890 718 { 891 719 struct snd_pcm_hw_constraint_list *cl = &mcasp->chconstr[stream]; 892 720 unsigned int *list = (unsigned int *) cl->list; 893 - int slots = mcasp->tdm_slots; 721 + int slots; 894 722 int i, count = 0; 723 + 724 + slots = mcasp_get_tdm_slots(mcasp, stream); 895 725 896 726 if (mcasp->tdm_mask[stream]) 897 727 slots = hweight32(mcasp->tdm_mask[stream]); ··· 959 785 return -EINVAL; 960 786 } 961 787 962 - mcasp->tdm_slots = slots; 788 + if (mcasp->async_mode) { 789 + if (tx_mask) { 790 + mcasp->tdm_slots_tx = slots; 791 + mcasp->slot_width_tx = slot_width; 792 + } 793 + if (rx_mask) { 794 + mcasp->tdm_slots_rx = slots; 795 + mcasp->slot_width_rx = slot_width; 796 + } 797 + } else { 798 + mcasp->tdm_slots_tx = slots; 799 + mcasp->tdm_slots_rx = slots; 800 + mcasp->slot_width_tx = slot_width; 801 + mcasp->slot_width_rx = slot_width; 802 + } 803 + 963 804 mcasp->tdm_mask[SNDRV_PCM_STREAM_PLAYBACK] = tx_mask; 964 805 mcasp->tdm_mask[SNDRV_PCM_STREAM_CAPTURE] = rx_mask; 965 - mcasp->slot_width = slot_width; 966 806 967 807 return davinci_mcasp_set_ch_constraints(mcasp); 968 808 } 969 809 970 810 static int davinci_config_channel_size(struct davinci_mcasp *mcasp, 971 - int sample_width) 811 + int sample_width, int stream) 972 812 { 973 813 u32 fmt; 974 814 u32 tx_rotate, rx_rotate, slot_width; 975 815 u32 mask = (1ULL << sample_width) - 1; 976 816 977 - if (mcasp->slot_width) 978 - slot_width = mcasp->slot_width; 979 - else if (mcasp->max_format_width) 980 - slot_width = mcasp->max_format_width; 981 - else 982 - slot_width = sample_width; 817 + slot_width = mcasp_get_slot_width(mcasp, stream); 818 + if (!slot_width) { 819 + if (mcasp->max_format_width) 820 + slot_width = mcasp->max_format_width; 821 + else 822 + slot_width = sample_width; 823 + } 983 824 /* 984 825 * TX rotation: 985 826 * right aligned formats: rotate w/ slot_width ··· 1017 828 fmt = (slot_width >> 1) - 1; 1018 829 1019 830 if (mcasp->op_mode != DAVINCI_MCASP_DIT_MODE) { 1020 - mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, RXSSZ(fmt), 1021 - RXSSZ(0x0F)); 1022 - mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXSSZ(fmt), 1023 - TXSSZ(0x0F)); 1024 - mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXROT(tx_rotate), 1025 - TXROT(7)); 1026 - mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, RXROT(rx_rotate), 1027 - RXROT(7)); 1028 - mcasp_set_reg(mcasp, DAVINCI_MCASP_RXMASK_REG, mask); 831 + if (!mcasp->async_mode || stream == SNDRV_PCM_STREAM_PLAYBACK) { 832 + mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXSSZ(fmt), 833 + TXSSZ(0x0F)); 834 + mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXROT(tx_rotate), 835 + TXROT(7)); 836 + mcasp_set_reg(mcasp, DAVINCI_MCASP_TXMASK_REG, mask); 837 + } 838 + if (!mcasp->async_mode || stream == SNDRV_PCM_STREAM_CAPTURE) { 839 + mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, RXSSZ(fmt), 840 + RXSSZ(0x0F)); 841 + mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, RXROT(rx_rotate), 842 + RXROT(7)); 843 + mcasp_set_reg(mcasp, DAVINCI_MCASP_RXMASK_REG, mask); 844 + } 1029 845 } else { 1030 846 /* 847 + * DIT mode only use TX serializers 1031 848 * according to the TRM it should be TXROT=0, this one works: 1032 849 * 16 bit to 23-8 (TXROT=6, rotate 24 bits) 1033 850 * 24 bit to 23-0 (TXROT=0, rotate 0 bits) ··· 1046 851 TXROT(7)); 1047 852 mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXSSZ(15), 1048 853 TXSSZ(0x0F)); 854 + mcasp_set_reg(mcasp, DAVINCI_MCASP_TXMASK_REG, mask); 1049 855 } 1050 - 1051 - mcasp_set_reg(mcasp, DAVINCI_MCASP_TXMASK_REG, mask); 1052 856 1053 857 return 0; 1054 858 } ··· 1059 865 int i; 1060 866 u8 tx_ser = 0; 1061 867 u8 rx_ser = 0; 1062 - u8 slots = mcasp->tdm_slots; 868 + int slots; 1063 869 u8 max_active_serializers, max_rx_serializers, max_tx_serializers; 1064 870 int active_serializers, numevt; 1065 871 u32 reg; 872 + 873 + slots = mcasp_get_tdm_slots(mcasp, stream); 1066 874 1067 875 /* In DIT mode we only allow maximum of one serializers for now */ 1068 876 if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE) ··· 1193 997 u32 mask = 0; 1194 998 u32 busel = 0; 1195 999 1196 - total_slots = mcasp->tdm_slots; 1000 + total_slots = mcasp_get_tdm_slots(mcasp, stream); 1197 1001 1198 1002 /* 1199 1003 * If more than one serializer is needed, then use them with ··· 1224 1028 mask |= (1 << i); 1225 1029 } 1226 1030 1227 - mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, TX_ASYNC); 1031 + if (mcasp->async_mode) 1032 + mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, TX_ASYNC); 1033 + else 1034 + mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, TX_ASYNC); 1228 1035 1229 1036 if (!mcasp->dat_port) 1230 1037 busel = TXSEL; ··· 1326 1127 1327 1128 static int davinci_mcasp_calc_clk_div(struct davinci_mcasp *mcasp, 1328 1129 unsigned int sysclk_freq, 1329 - unsigned int bclk_freq, bool set) 1130 + unsigned int bclk_freq, 1131 + int stream, 1132 + bool set) 1330 1133 { 1331 - u32 reg = mcasp_get_reg(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG); 1332 1134 int div = sysclk_freq / bclk_freq; 1333 1135 int rem = sysclk_freq % bclk_freq; 1334 1136 int error_ppm; 1335 1137 int aux_div = 1; 1138 + int bclk_div_id, auxclk_div_id; 1139 + bool auxclk_enabled; 1140 + 1141 + if (mcasp->async_mode && stream == SNDRV_PCM_STREAM_CAPTURE) { 1142 + auxclk_enabled = mcasp_get_reg(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG) & AHCLKRE; 1143 + bclk_div_id = MCASP_CLKDIV_BCLK_RXONLY; 1144 + auxclk_div_id = MCASP_CLKDIV_AUXCLK_RXONLY; 1145 + } else if (mcasp->async_mode && stream == SNDRV_PCM_STREAM_PLAYBACK) { 1146 + auxclk_enabled = mcasp_get_reg(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG) & AHCLKXE; 1147 + bclk_div_id = MCASP_CLKDIV_BCLK_TXONLY; 1148 + auxclk_div_id = MCASP_CLKDIV_AUXCLK_TXONLY; 1149 + } else { 1150 + auxclk_enabled = mcasp_get_reg(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG) & AHCLKXE; 1151 + bclk_div_id = MCASP_CLKDIV_BCLK; 1152 + auxclk_div_id = MCASP_CLKDIV_AUXCLK; 1153 + } 1336 1154 1337 1155 if (div > (ACLKXDIV_MASK + 1)) { 1338 - if (reg & AHCLKXE) { 1156 + if (auxclk_enabled) { 1339 1157 aux_div = div / (ACLKXDIV_MASK + 1); 1340 1158 if (div % (ACLKXDIV_MASK + 1)) 1341 1159 aux_div++; ··· 1382 1166 dev_info(mcasp->dev, "Sample-rate is off by %d PPM\n", 1383 1167 error_ppm); 1384 1168 1385 - __davinci_mcasp_set_clkdiv(mcasp, MCASP_CLKDIV_BCLK, div, 0); 1386 - if (reg & AHCLKXE) 1387 - __davinci_mcasp_set_clkdiv(mcasp, MCASP_CLKDIV_AUXCLK, 1388 - aux_div, 0); 1169 + __davinci_mcasp_set_clkdiv(mcasp, bclk_div_id, div, false); 1170 + if (auxclk_enabled) 1171 + __davinci_mcasp_set_clkdiv(mcasp, auxclk_div_id, 1172 + aux_div, false); 1389 1173 } 1390 1174 1391 1175 return error_ppm; ··· 1436 1220 int channels = params_channels(params); 1437 1221 int period_size = params_period_size(params); 1438 1222 int ret; 1223 + unsigned int sysclk_freq = mcasp_get_sysclk_freq(mcasp, substream->stream); 1439 1224 1440 1225 switch (params_format(params)) { 1441 1226 case SNDRV_PCM_FORMAT_U8: ··· 1477 1260 * If mcasp is BCLK master, and a BCLK divider was not provided by 1478 1261 * the machine driver, we need to calculate the ratio. 1479 1262 */ 1480 - if (mcasp->bclk_master && mcasp->bclk_div == 0 && mcasp->sysclk_freq) { 1481 - int slots = mcasp->tdm_slots; 1263 + if (mcasp->bclk_master && mcasp_get_bclk_div(mcasp, substream->stream) == 0 && 1264 + sysclk_freq) { 1265 + int slots, slot_width; 1482 1266 int rate = params_rate(params); 1483 1267 int sbits = params_width(params); 1484 1268 unsigned int bclk_target; 1485 1269 1486 - if (mcasp->slot_width) 1487 - sbits = mcasp->slot_width; 1270 + slots = mcasp_get_tdm_slots(mcasp, substream->stream); 1271 + 1272 + slot_width = mcasp_get_slot_width(mcasp, substream->stream); 1273 + if (slot_width) 1274 + sbits = slot_width; 1488 1275 1489 1276 if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE) 1490 1277 bclk_target = rate * sbits * slots; 1491 1278 else 1492 1279 bclk_target = rate * 128; 1493 1280 1494 - davinci_mcasp_calc_clk_div(mcasp, mcasp->sysclk_freq, 1495 - bclk_target, true); 1281 + davinci_mcasp_calc_clk_div(mcasp, sysclk_freq, 1282 + bclk_target, substream->stream, true); 1496 1283 } 1497 1284 1498 1285 ret = mcasp_common_hw_param(mcasp, substream->stream, ··· 1513 1292 if (ret) 1514 1293 return ret; 1515 1294 1516 - davinci_config_channel_size(mcasp, word_length); 1295 + davinci_config_channel_size(mcasp, word_length, substream->stream); 1517 1296 1518 - if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE) { 1297 + /* Channel constraints are disabled for async mode */ 1298 + if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE && !mcasp->async_mode) { 1519 1299 mcasp->channels = channels; 1520 1300 if (!mcasp->max_format_width) 1521 1301 mcasp->max_format_width = word_length; ··· 1560 1338 snd_pcm_format_t i; 1561 1339 1562 1340 snd_mask_none(&nfmt); 1563 - slot_width = rd->mcasp->slot_width; 1341 + slot_width = mcasp_get_slot_width(rd->mcasp, rd->stream); 1564 1342 1565 1343 pcm_for_each_format(i) { 1566 1344 if (snd_mask_test_format(fmt, i)) { ··· 1610 1388 struct snd_interval *ri = 1611 1389 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); 1612 1390 int sbits = params_width(params); 1613 - int slots = rd->mcasp->tdm_slots; 1391 + int slots, slot_width; 1614 1392 struct snd_interval range; 1615 1393 int i; 1616 1394 1617 - if (rd->mcasp->slot_width) 1618 - sbits = rd->mcasp->slot_width; 1395 + slots = mcasp_get_tdm_slots(rd->mcasp, rd->stream); 1396 + 1397 + slot_width = mcasp_get_slot_width(rd->mcasp, rd->stream); 1398 + if (slot_width) 1399 + sbits = slot_width; 1619 1400 1620 1401 snd_interval_any(&range); 1621 1402 range.empty = 1; ··· 1628 1403 uint bclk_freq = sbits * slots * 1629 1404 davinci_mcasp_dai_rates[i]; 1630 1405 unsigned int sysclk_freq; 1406 + unsigned int ratio; 1631 1407 int ppm; 1632 1408 1633 - if (rd->mcasp->auxclk_fs_ratio) 1634 - sysclk_freq = davinci_mcasp_dai_rates[i] * 1635 - rd->mcasp->auxclk_fs_ratio; 1409 + ratio = mcasp_get_auxclk_fs_ratio(rd->mcasp, rd->stream); 1410 + if (ratio) 1411 + sysclk_freq = davinci_mcasp_dai_rates[i] * ratio; 1636 1412 else 1637 - sysclk_freq = rd->mcasp->sysclk_freq; 1413 + sysclk_freq = mcasp_get_sysclk_freq(rd->mcasp, rd->stream); 1638 1414 1639 1415 ppm = davinci_mcasp_calc_clk_div(rd->mcasp, sysclk_freq, 1640 - bclk_freq, false); 1416 + bclk_freq, rd->stream, false); 1641 1417 if (abs(ppm) < DAVINCI_MAX_RATE_ERROR_PPM) { 1642 1418 if (range.empty) { 1643 1419 range.min = davinci_mcasp_dai_rates[i]; ··· 1664 1438 struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); 1665 1439 struct snd_mask nfmt; 1666 1440 int rate = params_rate(params); 1667 - int slots = rd->mcasp->tdm_slots; 1441 + int slots; 1668 1442 int count = 0; 1669 1443 snd_pcm_format_t i; 1444 + 1445 + slots = mcasp_get_tdm_slots(rd->mcasp, rd->stream); 1670 1446 1671 1447 snd_mask_none(&nfmt); 1672 1448 ··· 1676 1448 if (snd_mask_test_format(fmt, i)) { 1677 1449 uint sbits = snd_pcm_format_width(i); 1678 1450 unsigned int sysclk_freq; 1679 - int ppm; 1451 + unsigned int ratio; 1452 + int ppm, slot_width; 1680 1453 1681 - if (rd->mcasp->auxclk_fs_ratio) 1682 - sysclk_freq = rate * 1683 - rd->mcasp->auxclk_fs_ratio; 1454 + ratio = mcasp_get_auxclk_fs_ratio(rd->mcasp, rd->stream); 1455 + if (ratio) 1456 + sysclk_freq = rate * ratio; 1684 1457 else 1685 - sysclk_freq = rd->mcasp->sysclk_freq; 1458 + sysclk_freq = mcasp_get_sysclk_freq(rd->mcasp, rd->stream); 1686 1459 1687 - if (rd->mcasp->slot_width) 1688 - sbits = rd->mcasp->slot_width; 1460 + slot_width = mcasp_get_slot_width(rd->mcasp, rd->stream); 1461 + if (slot_width) 1462 + sbits = slot_width; 1689 1463 1690 1464 ppm = davinci_mcasp_calc_clk_div(rd->mcasp, sysclk_freq, 1691 1465 sbits * slots * rate, 1692 - false); 1466 + rd->stream, false); 1693 1467 if (abs(ppm) < DAVINCI_MAX_RATE_ERROR_PPM) { 1694 1468 snd_mask_set_format(&nfmt, i); 1695 1469 count++; ··· 1728 1498 &mcasp->ruledata[substream->stream]; 1729 1499 u32 max_channels = 0; 1730 1500 int i, dir, ret; 1731 - int tdm_slots = mcasp->tdm_slots; 1501 + int tdm_slots; 1732 1502 u8 *numevt; 1733 1503 1734 1504 /* Do not allow more then one stream per direction */ ··· 1736 1506 return -EBUSY; 1737 1507 1738 1508 mcasp->substreams[substream->stream] = substream; 1509 + 1510 + tdm_slots = mcasp_get_tdm_slots(mcasp, substream->stream); 1739 1511 1740 1512 if (mcasp->tdm_mask[substream->stream]) 1741 1513 tdm_slots = hweight32(mcasp->tdm_mask[substream->stream]); ··· 1760 1528 } 1761 1529 ruledata->serializers = max_channels; 1762 1530 ruledata->mcasp = mcasp; 1531 + ruledata->stream = substream->stream; 1763 1532 max_channels *= tdm_slots; 1764 1533 /* 1765 1534 * If the already active stream has less channels than the calculated ··· 1768 1535 * is in use we need to use that as a constraint for the second stream. 1769 1536 * Otherwise (first stream or less allowed channels or more than one 1770 1537 * serializer in use) we use the calculated constraint. 1538 + * 1539 + * However, in async mode, TX and RX have independent clocks and can 1540 + * use different configurations, so don't apply the constraint. 1771 1541 */ 1772 1542 if (mcasp->channels && mcasp->channels < max_channels && 1773 - ruledata->serializers == 1) 1543 + ruledata->serializers == 1 && 1544 + !mcasp->async_mode) 1774 1545 max_channels = mcasp->channels; 1775 1546 /* 1776 1547 * But we can always allow channels upto the amount of ··· 1791 1554 0, SNDRV_PCM_HW_PARAM_CHANNELS, 1792 1555 &mcasp->chconstr[substream->stream]); 1793 1556 1794 - if (mcasp->max_format_width) { 1557 + if (mcasp->max_format_width && !mcasp->async_mode) { 1795 1558 /* 1796 1559 * Only allow formats which require same amount of bits on the 1797 - * bus as the currently running stream 1560 + * bus as the currently running stream to ensure sync mode 1798 1561 */ 1799 1562 ret = snd_pcm_hw_rule_add(substream->runtime, 0, 1800 1563 SNDRV_PCM_HW_PARAM_FORMAT, ··· 1803 1566 SNDRV_PCM_HW_PARAM_FORMAT, -1); 1804 1567 if (ret) 1805 1568 return ret; 1806 - } 1807 - else if (mcasp->slot_width) { 1569 + } else if (mcasp_get_slot_width(mcasp, substream->stream)) { 1808 1570 /* Only allow formats require <= slot_width bits on the bus */ 1809 1571 ret = snd_pcm_hw_rule_add(substream->runtime, 0, 1810 1572 SNDRV_PCM_HW_PARAM_FORMAT, ··· 1818 1582 * If we rely on implicit BCLK divider setting we should 1819 1583 * set constraints based on what we can provide. 1820 1584 */ 1821 - if (mcasp->bclk_master && mcasp->bclk_div == 0 && mcasp->sysclk_freq) { 1585 + if (mcasp->bclk_master && mcasp_get_bclk_div(mcasp, substream->stream) == 0 && 1586 + mcasp_get_sysclk_freq(mcasp, substream->stream)) { 1822 1587 ret = snd_pcm_hw_rule_add(substream->runtime, 0, 1823 1588 SNDRV_PCM_HW_PARAM_RATE, 1824 1589 davinci_mcasp_hw_rule_rate, ··· 1996 1759 .formats = DAVINCI_MCASP_PCM_FMTS, 1997 1760 }, 1998 1761 .ops = &davinci_mcasp_dai_ops, 1999 - 2000 - .symmetric_rate = 1, 2001 1762 }, 2002 1763 { 2003 1764 .name = "davinci-mcasp.1", ··· 2153 1918 goto out; 2154 1919 } 2155 1920 1921 + /* Parse TX-specific TDM slot and use it as default for RX */ 2156 1922 if (of_property_read_u32(np, "tdm-slots", &val) == 0) { 2157 1923 if (val < 2 || val > 32) { 2158 - dev_err(&pdev->dev, "tdm-slots must be in rage [2-32]\n"); 1924 + dev_err(&pdev->dev, "tdm-slots must be in range [2-32]\n"); 2159 1925 return -EINVAL; 2160 1926 } 2161 1927 2162 - pdata->tdm_slots = val; 1928 + pdata->tdm_slots_tx = val; 1929 + pdata->tdm_slots_rx = val; 2163 1930 } else if (pdata->op_mode == DAVINCI_MCASP_IIS_MODE) { 2164 1931 mcasp->missing_audio_param = true; 2165 1932 goto out; 2166 1933 } 1934 + 1935 + /* Parse RX-specific TDM slot count if provided */ 1936 + if (of_property_read_u32(np, "tdm-slots-rx", &val) == 0) { 1937 + if (val < 2 || val > 32) { 1938 + dev_err(&pdev->dev, "tdm-slots-rx must be in range [2-32]\n"); 1939 + return -EINVAL; 1940 + } 1941 + 1942 + pdata->tdm_slots_rx = val; 1943 + } 1944 + 1945 + if (pdata->op_mode != DAVINCI_MCASP_DIT_MODE) 1946 + mcasp->async_mode = of_property_read_bool(np, "ti,async-mode"); 2167 1947 2168 1948 of_serial_dir32 = of_get_property(np, "serial-dir", &val); 2169 1949 val /= sizeof(u32); ··· 2205 1955 if (of_property_read_u32(np, "rx-num-evt", &val) == 0) 2206 1956 pdata->rxnumevt = val; 2207 1957 2208 - if (of_property_read_u32(np, "auxclk-fs-ratio", &val) == 0) 2209 - mcasp->auxclk_fs_ratio = val; 1958 + /* Parse TX-specific auxclk/fs ratio and use it as default for RX */ 1959 + if (of_property_read_u32(np, "auxclk-fs-ratio", &val) == 0) { 1960 + mcasp->auxclk_fs_ratio_tx = val; 1961 + mcasp->auxclk_fs_ratio_rx = val; 1962 + } 1963 + 1964 + /* Parse RX-specific auxclk/fs ratio if provided */ 1965 + if (of_property_read_u32(np, "auxclk-fs-ratio-rx", &val) == 0) 1966 + mcasp->auxclk_fs_ratio_rx = val; 2210 1967 2211 1968 if (of_property_read_u32(np, "dismod", &val) == 0) { 2212 1969 if (val == 0 || val == 2 || val == 3) { ··· 2242 1985 mcasp->op_mode = pdata->op_mode; 2243 1986 /* sanity check for tdm slots parameter */ 2244 1987 if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE) { 2245 - if (pdata->tdm_slots < 2) { 2246 - dev_warn(&pdev->dev, "invalid tdm slots: %d\n", 2247 - pdata->tdm_slots); 2248 - mcasp->tdm_slots = 2; 2249 - } else if (pdata->tdm_slots > 32) { 2250 - dev_warn(&pdev->dev, "invalid tdm slots: %d\n", 2251 - pdata->tdm_slots); 2252 - mcasp->tdm_slots = 32; 1988 + if (pdata->tdm_slots_tx < 2) { 1989 + dev_warn(&pdev->dev, "invalid tdm tx slots: %d\n", 1990 + pdata->tdm_slots_tx); 1991 + mcasp->tdm_slots_tx = 2; 1992 + } else if (pdata->tdm_slots_tx > 32) { 1993 + dev_warn(&pdev->dev, "invalid tdm tx slots: %d\n", 1994 + pdata->tdm_slots_tx); 1995 + mcasp->tdm_slots_tx = 32; 2253 1996 } else { 2254 - mcasp->tdm_slots = pdata->tdm_slots; 1997 + mcasp->tdm_slots_tx = pdata->tdm_slots_tx; 1998 + } 1999 + 2000 + if (pdata->tdm_slots_rx < 2) { 2001 + dev_warn(&pdev->dev, "invalid tdm rx slots: %d\n", 2002 + pdata->tdm_slots_rx); 2003 + mcasp->tdm_slots_rx = 2; 2004 + } else if (pdata->tdm_slots_rx > 32) { 2005 + dev_warn(&pdev->dev, "invalid tdm rx slots: %d\n", 2006 + pdata->tdm_slots_rx); 2007 + mcasp->tdm_slots_rx = 32; 2008 + } else { 2009 + mcasp->tdm_slots_rx = pdata->tdm_slots_rx; 2255 2010 } 2256 2011 } else { 2257 - mcasp->tdm_slots = 32; 2012 + mcasp->tdm_slots_tx = 32; 2013 + mcasp->tdm_slots_rx = 32; 2014 + } 2015 + 2016 + /* Different TX/RX slot counts require async mode */ 2017 + if (pdata->op_mode != DAVINCI_MCASP_DIT_MODE && 2018 + mcasp->tdm_slots_tx != mcasp->tdm_slots_rx && !mcasp->async_mode) { 2019 + dev_err(&pdev->dev, 2020 + "Different TX (%d) and RX (%d) TDM slots require ti,async-mode\n", 2021 + mcasp->tdm_slots_tx, mcasp->tdm_slots_rx); 2022 + return -EINVAL; 2023 + } 2024 + 2025 + /* Different TX/RX auxclk-fs-ratio require async mode */ 2026 + if (pdata->op_mode != DAVINCI_MCASP_DIT_MODE && 2027 + mcasp->auxclk_fs_ratio_tx && mcasp->auxclk_fs_ratio_rx && 2028 + mcasp->auxclk_fs_ratio_tx != mcasp->auxclk_fs_ratio_rx && !mcasp->async_mode) { 2029 + dev_err(&pdev->dev, 2030 + "Different TX (%d) and RX (%d) auxclk-fs-ratio require ti,async-mode\n", 2031 + mcasp->auxclk_fs_ratio_tx, mcasp->auxclk_fs_ratio_rx); 2032 + return -EINVAL; 2258 2033 } 2259 2034 2260 2035 mcasp->num_serializer = pdata->num_serializer;
+10
sound/soc/ti/davinci-mcasp.h
··· 298 298 /* Source of High-frequency transmit/receive clock */ 299 299 #define MCASP_CLK_HCLK_AHCLK 0 /* AHCLKX/R */ 300 300 #define MCASP_CLK_HCLK_AUXCLK 1 /* Internal functional clock */ 301 + #define MCASP_CLK_HCLK_AHCLK_TXONLY 2 /* AHCLKX for TX only */ 302 + #define MCASP_CLK_HCLK_AHCLK_RXONLY 3 /* AHCLKR for RX only */ 303 + #define MCASP_CLK_HCLK_AUXCLK_TXONLY 4 /* AUXCLK for TX only */ 304 + #define MCASP_CLK_HCLK_AUXCLK_RXONLY 5 /* AUXCLK for RX only */ 301 305 302 306 /* clock divider IDs */ 303 307 #define MCASP_CLKDIV_AUXCLK 0 /* HCLK divider from AUXCLK */ 304 308 #define MCASP_CLKDIV_BCLK 1 /* BCLK divider from HCLK */ 305 309 #define MCASP_CLKDIV_BCLK_FS_RATIO 2 /* to set BCLK FS ration */ 310 + #define MCASP_CLKDIV_AUXCLK_TXONLY 3 /* AUXCLK divider for TX only */ 311 + #define MCASP_CLKDIV_AUXCLK_RXONLY 4 /* AUXCLK divider for RX only */ 312 + #define MCASP_CLKDIV_BCLK_TXONLY 5 /* BCLK divider for TX only */ 313 + #define MCASP_CLKDIV_BCLK_RXONLY 6 /* BCLK divider for RX only */ 314 + #define MCASP_CLKDIV_BCLK_FS_RATIO_TXONLY 7 /* BCLK/FS ratio for TX only */ 315 + #define MCASP_CLKDIV_BCLK_FS_RATIO_RXONLY 8 /* BCLK/FS ratio for RX only*/ 306 316 307 317 #endif /* DAVINCI_MCASP_H */