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

Merge series from Sen Wang <sen@ti.com>:

This series adds asynchronous mode support to the McASP driver, which
enables independent configuration of bitclocks, frame sync, and audio
configurations between tx(playback) and rx(record). And achieves
simultaneous playback & record using different audio configurations.

It also adds two clean up patches to the McASP driver that disambiguate
and simplifies the logic which avoids the async enhancement from being
too convoluted to review and analyze.

The implementation is based on vendor documentation and patches tested in
both SK-AM62P-LP (sync mode, McASP slave) and AM62D-EVM
(async mode, McASP master, rx & tx has different TDM configs).
Testing verifies async mode functionality while maintaining backward
compatibility with the default sync mode.

Bootlog and Async mode tests on AM62D-EVM: [0]

[0]: https://gist.github.com/SenWang125/f31f9172b186d414695e37c8b9ef127d

+481 -113
+66 -5
Documentation/devicetree/bindings/sound/davinci-mcasp-audio.yaml
··· 40 40 tdm-slots: 41 41 $ref: /schemas/types.yaml#/definitions/uint32 42 42 description: 43 - number of channels over one serializer 44 - the property is ignored in DIT mode 43 + Number of channels over one serializer. This property 44 + specifies the TX playback TDM slot count, along with default RX slot count 45 + if tdm-slots-rx is not specified. 46 + The property is ignored in DIT mode. 45 47 minimum: 2 46 48 maximum: 32 49 + 50 + tdm-slots-rx: 51 + $ref: /schemas/types.yaml#/definitions/uint32 52 + description: 53 + Number of RX capture channels over one serializer. If specified, 54 + allows independent RX TDM slot count separate from TX. Requires 55 + ti,async-mode to be enabled for independent TX/RX clock rates. 56 + The property is ignored in DIT mode. 57 + minimum: 2 58 + maximum: 32 59 + 60 + ti,async-mode: 61 + description: 62 + Specify to allow independent TX & RX clocking, 63 + to enable audio playback & record with different sampling rate, 64 + and different number of bits per frame. 65 + if property is omitted, TX and RX will share same bit clock and frame clock signals, 66 + thus RX need to use same bits per frame and sampling rate as TX in synchronous mode. 67 + the property is ignored in DIT mode (as DIT is TX-only) 68 + type: boolean 47 69 48 70 serial-dir: 49 71 description: ··· 147 125 148 126 auxclk-fs-ratio: 149 127 $ref: /schemas/types.yaml#/definitions/uint32 150 - description: ratio of AUCLK and FS rate if applicable 128 + description: 129 + Ratio of AUCLK and FS rate if applicable. This property specifies 130 + the TX ratio, along with default RX ratio if auxclk-fs-ratio-rx 131 + is not specified. 132 + When not specified, the inputted system clock frequency via set_sysclk 133 + callback by the machine driver is used for divider calculation. 134 + 135 + auxclk-fs-ratio-rx: 136 + $ref: /schemas/types.yaml#/definitions/uint32 137 + description: 138 + Ratio of AUCLK and FS rate for RX. If specified, allows 139 + for a different RX ratio. Requires ti,async-mode to be 140 + enabled when the ratio differs from auxclk-fs-ratio. 141 + When not specified, it defaults to the value of auxclk-fs-ratio. 142 + The property is ignored in DIT mode. 151 143 152 144 gpio-controller: true 153 145 ··· 206 170 - $ref: dai-common.yaml# 207 171 - if: 208 172 properties: 209 - opmode: 173 + op-mode: 210 174 enum: 211 175 - 0 212 - 213 176 then: 214 177 required: 215 178 - tdm-slots 179 + 180 + - if: 181 + properties: 182 + op-mode: 183 + const: 1 184 + then: 185 + properties: 186 + tdm-slots: false 187 + tdm-slots-rx: false 188 + ti,async-mode: false 189 + auxclk-fs-ratio-rx: false 190 + 191 + - if: 192 + required: 193 + - tdm-slots-rx 194 + then: 195 + required: 196 + - ti,async-mode 197 + 198 + - if: 199 + required: 200 + - auxclk-fs-ratio-rx 201 + then: 202 + required: 203 + - ti,async-mode 216 204 217 205 unevaluatedProperties: false 218 206 ··· 250 190 interrupt-names = "tx", "rx"; 251 191 op-mode = <0>; /* MCASP_IIS_MODE */ 252 192 tdm-slots = <2>; 193 + ti,async-mode; 253 194 dmas = <&main_udmap 0xc400>, <&main_udmap 0x4400>; 254 195 dma-names = "tx", "rx"; 255 196 serial-dir = <
+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;
+403 -107
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 ··· 187 180 188 181 static bool mcasp_is_synchronous(struct davinci_mcasp *mcasp) 189 182 { 190 - u32 rxfmctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG); 191 183 u32 aclkxctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG); 192 184 193 - return !(aclkxctl & TX_ASYNC) && rxfmctl & AFSRE; 185 + return !(aclkxctl & TX_ASYNC); 186 + } 187 + 188 + static bool mcasp_is_frame_producer(struct davinci_mcasp *mcasp) 189 + { 190 + u32 rxfmctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG); 191 + 192 + return rxfmctl & AFSRE; 194 193 } 195 194 196 195 static inline void mcasp_set_clk_pdir(struct davinci_mcasp *mcasp, bool enable) ··· 204 191 u32 bit = PIN_BIT_AMUTE; 205 192 206 193 for_each_set_bit_from(bit, &mcasp->pdir, PIN_BIT_AFSR + 1) { 194 + if (enable) 195 + mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(bit)); 196 + else 197 + mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(bit)); 198 + } 199 + } 200 + 201 + static inline void mcasp_set_clk_pdir_stream(struct davinci_mcasp *mcasp, 202 + int stream, bool enable) 203 + { 204 + u32 bit, bit_end; 205 + 206 + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { 207 + bit = PIN_BIT_ACLKX; 208 + bit_end = PIN_BIT_AFSX + 1; 209 + } else { 210 + bit = PIN_BIT_ACLKR; 211 + bit_end = PIN_BIT_AFSR + 1; 212 + } 213 + 214 + for_each_set_bit_from(bit, &mcasp->pdir, bit_end) { 207 215 if (enable) 208 216 mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(bit)); 209 217 else ··· 244 210 } 245 211 } 246 212 213 + static inline int mcasp_get_tdm_slots(struct davinci_mcasp *mcasp, int stream) 214 + { 215 + return (stream == SNDRV_PCM_STREAM_PLAYBACK) ? 216 + mcasp->tdm_slots_tx : mcasp->tdm_slots_rx; 217 + } 218 + 219 + static inline int mcasp_get_slot_width(struct davinci_mcasp *mcasp, int stream) 220 + { 221 + return (stream == SNDRV_PCM_STREAM_PLAYBACK) ? 222 + mcasp->slot_width_tx : mcasp->slot_width_rx; 223 + } 224 + 225 + static inline unsigned int mcasp_get_sysclk_freq(struct davinci_mcasp *mcasp, int stream) 226 + { 227 + return (stream == SNDRV_PCM_STREAM_PLAYBACK) ? 228 + mcasp->sysclk_freq_tx : mcasp->sysclk_freq_rx; 229 + } 230 + 231 + static inline unsigned int mcasp_get_bclk_div(struct davinci_mcasp *mcasp, int stream) 232 + { 233 + return (stream == SNDRV_PCM_STREAM_PLAYBACK) ? 234 + mcasp->bclk_div_tx : mcasp->bclk_div_rx; 235 + } 236 + 237 + static inline unsigned int mcasp_get_auxclk_fs_ratio(struct davinci_mcasp *mcasp, int stream) 238 + { 239 + return (stream == SNDRV_PCM_STREAM_PLAYBACK) ? 240 + mcasp->auxclk_fs_ratio_tx : mcasp->auxclk_fs_ratio_rx; 241 + } 242 + 247 243 static void mcasp_start_rx(struct davinci_mcasp *mcasp) 248 244 { 249 245 if (mcasp->rxnumevt) { /* enable FIFO */ ··· 289 225 /* 290 226 * When ASYNC == 0 the transmit and receive sections operate 291 227 * synchronously from the transmit clock and frame sync. We need to make 292 - * sure that the TX signlas are enabled when starting reception. 228 + * sure that the TX signals are enabled when starting reception, 229 + * when the McASP is the producer. 293 230 */ 294 - if (mcasp_is_synchronous(mcasp)) { 231 + if (mcasp_is_frame_producer(mcasp) && mcasp_is_synchronous(mcasp)) { 295 232 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST); 296 233 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST); 297 - mcasp_set_clk_pdir(mcasp, true); 298 234 } 235 + if (mcasp_is_synchronous(mcasp)) 236 + mcasp_set_clk_pdir(mcasp, true); 237 + else 238 + mcasp_set_clk_pdir_stream(mcasp, SNDRV_PCM_STREAM_CAPTURE, true); 299 239 300 240 /* Activate serializer(s) */ 301 241 mcasp_set_reg(mcasp, DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF); ··· 308 240 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXSMRST); 309 241 /* Release Frame Sync generator */ 310 242 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXFSRST); 311 - if (mcasp_is_synchronous(mcasp)) 243 + if (mcasp_is_frame_producer(mcasp) && mcasp_is_synchronous(mcasp)) 312 244 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXFSRST); 313 245 314 246 /* enable receive IRQs */ ··· 330 262 /* Start clocks */ 331 263 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST); 332 264 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST); 333 - mcasp_set_clk_pdir(mcasp, true); 265 + if (mcasp_is_synchronous(mcasp)) 266 + mcasp_set_clk_pdir(mcasp, true); 267 + else 268 + mcasp_set_clk_pdir_stream(mcasp, SNDRV_PCM_STREAM_PLAYBACK, true); 334 269 335 270 /* Activate serializer(s) */ 336 271 mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF); ··· 376 305 /* 377 306 * In synchronous mode stop the TX clocks if no other stream is 378 307 * running 308 + * Otherwise in async mode only stop RX clocks 379 309 */ 380 - if (mcasp_is_synchronous(mcasp) && !mcasp->streams) { 310 + if (mcasp_is_synchronous(mcasp) && !mcasp->streams) 381 311 mcasp_set_clk_pdir(mcasp, false); 312 + else if (!mcasp_is_synchronous(mcasp)) 313 + mcasp_set_clk_pdir_stream(mcasp, SNDRV_PCM_STREAM_CAPTURE, false); 314 + /* 315 + * When McASP is the producer and operating in synchronous mode, 316 + * stop the transmit clocks if no other stream is running. As 317 + * tx & rx operate synchronously from the transmit clock. 318 + */ 319 + if (mcasp_is_frame_producer(mcasp) && mcasp_is_synchronous(mcasp) && !mcasp->streams) 382 320 mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, 0); 383 - } 384 321 385 322 mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, 0); 386 323 mcasp_set_reg(mcasp, DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF); ··· 411 332 /* 412 333 * In synchronous mode keep TX clocks running if the capture stream is 413 334 * still running. 335 + * Otherwise in async mode only stop TX clocks 414 336 */ 415 - if (mcasp_is_synchronous(mcasp) && mcasp->streams) 337 + if (mcasp_is_frame_producer(mcasp) && mcasp_is_synchronous(mcasp) && mcasp->streams) 416 338 val = TXHCLKRST | TXCLKRST | TXFSRST; 417 - else 339 + if (mcasp_is_synchronous(mcasp) && !mcasp->streams) 418 340 mcasp_set_clk_pdir(mcasp, false); 341 + else if (!mcasp_is_synchronous(mcasp)) 342 + mcasp_set_clk_pdir_stream(mcasp, SNDRV_PCM_STREAM_PLAYBACK, false); 419 343 420 344 421 345 mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, val); ··· 702 620 AHCLKRDIV(div - 1), AHCLKRDIV_MASK); 703 621 break; 704 622 623 + case MCASP_CLKDIV_AUXCLK_TXONLY: /* MCLK divider for TX only */ 624 + mcasp_mod_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, 625 + AHCLKXDIV(div - 1), AHCLKXDIV_MASK); 626 + break; 627 + 628 + case MCASP_CLKDIV_AUXCLK_RXONLY: /* MCLK divider for RX only */ 629 + mcasp_mod_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, 630 + AHCLKRDIV(div - 1), AHCLKRDIV_MASK); 631 + break; 632 + 705 633 case MCASP_CLKDIV_BCLK: /* BCLK divider */ 706 634 mcasp_mod_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, 707 635 ACLKXDIV(div - 1), ACLKXDIV_MASK); 708 636 mcasp_mod_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, 709 637 ACLKRDIV(div - 1), ACLKRDIV_MASK); 638 + if (explicit) { 639 + mcasp->bclk_div_tx = div; 640 + mcasp->bclk_div_rx = div; 641 + } 642 + break; 643 + 644 + case MCASP_CLKDIV_BCLK_TXONLY: /* BCLK divider for TX only */ 645 + mcasp_mod_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, 646 + ACLKXDIV(div - 1), ACLKXDIV_MASK); 710 647 if (explicit) 711 - mcasp->bclk_div = div; 648 + mcasp->bclk_div_tx = div; 649 + break; 650 + 651 + case MCASP_CLKDIV_BCLK_RXONLY: /* BCLK divider for RX only */ 652 + mcasp_mod_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, 653 + ACLKRDIV(div - 1), ACLKRDIV_MASK); 654 + if (explicit) 655 + mcasp->bclk_div_rx = div; 712 656 break; 713 657 714 658 case MCASP_CLKDIV_BCLK_FS_RATIO: ··· 748 640 * tdm_slot width by dividing the ratio by the 749 641 * number of configured tdm slots. 750 642 */ 751 - mcasp->slot_width = div / mcasp->tdm_slots; 752 - if (div % mcasp->tdm_slots) 643 + mcasp->slot_width_tx = div / mcasp->tdm_slots_tx; 644 + if (div % mcasp->tdm_slots_tx) 753 645 dev_warn(mcasp->dev, 754 - "%s(): BCLK/LRCLK %d is not divisible by %d tdm slots", 755 - __func__, div, mcasp->tdm_slots); 646 + "%s(): BCLK/LRCLK %d is not divisible by %d tx tdm slots", 647 + __func__, div, mcasp->tdm_slots_tx); 648 + 649 + mcasp->slot_width_rx = div / mcasp->tdm_slots_rx; 650 + if (div % mcasp->tdm_slots_rx) 651 + dev_warn(mcasp->dev, 652 + "%s(): BCLK/LRCLK %d is not divisible by %d rx tdm slots", 653 + __func__, div, mcasp->tdm_slots_rx); 654 + break; 655 + 656 + case MCASP_CLKDIV_BCLK_FS_RATIO_TXONLY: 657 + mcasp->slot_width_tx = div / mcasp->tdm_slots_tx; 658 + if (div % mcasp->tdm_slots_tx) 659 + dev_warn(mcasp->dev, 660 + "%s(): BCLK/LRCLK %d is not divisible by %d tx tdm slots", 661 + __func__, div, mcasp->tdm_slots_tx); 662 + break; 663 + 664 + case MCASP_CLKDIV_BCLK_FS_RATIO_RXONLY: 665 + mcasp->slot_width_rx = div / mcasp->tdm_slots_rx; 666 + if (div % mcasp->tdm_slots_rx) 667 + dev_warn(mcasp->dev, 668 + "%s(): BCLK/LRCLK %d is not divisible by %d rx tdm slots", 669 + __func__, div, mcasp->tdm_slots_rx); 756 670 break; 757 671 758 672 default: ··· 808 678 mcasp_clr_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, 809 679 AHCLKRE); 810 680 clear_bit(PIN_BIT_AHCLKX, &mcasp->pdir); 681 + mcasp->sysclk_freq_tx = freq; 682 + mcasp->sysclk_freq_rx = freq; 683 + break; 684 + case MCASP_CLK_HCLK_AHCLK_TXONLY: 685 + mcasp_clr_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, 686 + AHCLKXE); 687 + clear_bit(PIN_BIT_AHCLKX, &mcasp->pdir); 688 + mcasp->sysclk_freq_tx = freq; 689 + break; 690 + case MCASP_CLK_HCLK_AHCLK_RXONLY: 691 + mcasp_clr_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, 692 + AHCLKRE); 693 + clear_bit(PIN_BIT_AHCLKR, &mcasp->pdir); 694 + mcasp->sysclk_freq_rx = freq; 811 695 break; 812 696 case MCASP_CLK_HCLK_AUXCLK: 813 697 mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, ··· 829 685 mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, 830 686 AHCLKRE); 831 687 set_bit(PIN_BIT_AHCLKX, &mcasp->pdir); 688 + mcasp->sysclk_freq_tx = freq; 689 + mcasp->sysclk_freq_rx = freq; 690 + break; 691 + case MCASP_CLK_HCLK_AUXCLK_TXONLY: 692 + mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, 693 + AHCLKXE); 694 + set_bit(PIN_BIT_AHCLKX, &mcasp->pdir); 695 + mcasp->sysclk_freq_tx = freq; 696 + break; 697 + case MCASP_CLK_HCLK_AUXCLK_RXONLY: 698 + mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, 699 + AHCLKRE); 700 + set_bit(PIN_BIT_AHCLKR, &mcasp->pdir); 701 + mcasp->sysclk_freq_rx = freq; 832 702 break; 833 703 default: 834 704 dev_err(mcasp->dev, "Invalid clk id: %d\n", clk_id); 835 705 goto out; 836 706 } 837 707 } 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); 708 + /* McASP is clock master, select AUXCLK as HCLK */ 709 + switch (clk_id) { 710 + case MCASP_CLK_HCLK_AUXCLK_TXONLY: 711 + mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, 712 + AHCLKXE); 713 + set_bit(PIN_BIT_AHCLKX, &mcasp->pdir); 714 + mcasp->sysclk_freq_tx = freq; 715 + break; 716 + case MCASP_CLK_HCLK_AUXCLK_RXONLY: 717 + mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, 718 + AHCLKRE); 719 + set_bit(PIN_BIT_AHCLKR, &mcasp->pdir); 720 + mcasp->sysclk_freq_rx = freq; 721 + break; 722 + default: 723 + mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, 724 + AHCLKXE); 725 + mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, 726 + AHCLKRE); 727 + set_bit(PIN_BIT_AHCLKX, &mcasp->pdir); 728 + set_bit(PIN_BIT_AHCLKR, &mcasp->pdir); 729 + mcasp->sysclk_freq_tx = freq; 730 + mcasp->sysclk_freq_rx = freq; 731 + break; 732 + } 842 733 } 843 734 /* 844 735 * When AHCLK X/R is selected to be output it means that the HCLK is 845 736 * the same clock - coming via AUXCLK. 846 737 */ 847 - mcasp->sysclk_freq = freq; 848 738 out: 849 739 pm_runtime_put(mcasp->dev); 850 740 return 0; ··· 890 712 { 891 713 struct snd_pcm_hw_constraint_list *cl = &mcasp->chconstr[stream]; 892 714 unsigned int *list = (unsigned int *) cl->list; 893 - int slots = mcasp->tdm_slots; 715 + int slots; 894 716 int i, count = 0; 717 + 718 + slots = mcasp_get_tdm_slots(mcasp, stream); 895 719 896 720 if (mcasp->tdm_mask[stream]) 897 721 slots = hweight32(mcasp->tdm_mask[stream]); ··· 959 779 return -EINVAL; 960 780 } 961 781 962 - mcasp->tdm_slots = slots; 782 + if (mcasp->async_mode) { 783 + if (tx_mask) { 784 + mcasp->tdm_slots_tx = slots; 785 + mcasp->slot_width_tx = slot_width; 786 + } 787 + if (rx_mask) { 788 + mcasp->tdm_slots_rx = slots; 789 + mcasp->slot_width_rx = slot_width; 790 + } 791 + } else { 792 + mcasp->tdm_slots_tx = slots; 793 + mcasp->tdm_slots_rx = slots; 794 + mcasp->slot_width_tx = slot_width; 795 + mcasp->slot_width_rx = slot_width; 796 + } 797 + 963 798 mcasp->tdm_mask[SNDRV_PCM_STREAM_PLAYBACK] = tx_mask; 964 799 mcasp->tdm_mask[SNDRV_PCM_STREAM_CAPTURE] = rx_mask; 965 - mcasp->slot_width = slot_width; 966 800 967 801 return davinci_mcasp_set_ch_constraints(mcasp); 968 802 } 969 803 970 804 static int davinci_config_channel_size(struct davinci_mcasp *mcasp, 971 - int sample_width) 805 + int sample_width, int stream) 972 806 { 973 807 u32 fmt; 974 808 u32 tx_rotate, rx_rotate, slot_width; 975 809 u32 mask = (1ULL << sample_width) - 1; 976 810 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; 811 + slot_width = mcasp_get_slot_width(mcasp, stream); 812 + if (!slot_width) { 813 + if (mcasp->max_format_width) 814 + slot_width = mcasp->max_format_width; 815 + else 816 + slot_width = sample_width; 817 + } 983 818 /* 984 819 * TX rotation: 985 820 * right aligned formats: rotate w/ slot_width ··· 1017 822 fmt = (slot_width >> 1) - 1; 1018 823 1019 824 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); 825 + if (!mcasp->async_mode || stream == SNDRV_PCM_STREAM_PLAYBACK) { 826 + mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXSSZ(fmt), 827 + TXSSZ(0x0F)); 828 + mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXROT(tx_rotate), 829 + TXROT(7)); 830 + mcasp_set_reg(mcasp, DAVINCI_MCASP_TXMASK_REG, mask); 831 + } 832 + if (!mcasp->async_mode || stream == SNDRV_PCM_STREAM_CAPTURE) { 833 + mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, RXSSZ(fmt), 834 + RXSSZ(0x0F)); 835 + mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, RXROT(rx_rotate), 836 + RXROT(7)); 837 + mcasp_set_reg(mcasp, DAVINCI_MCASP_RXMASK_REG, mask); 838 + } 1029 839 } else { 1030 840 /* 841 + * DIT mode only use TX serializers 1031 842 * according to the TRM it should be TXROT=0, this one works: 1032 843 * 16 bit to 23-8 (TXROT=6, rotate 24 bits) 1033 844 * 24 bit to 23-0 (TXROT=0, rotate 0 bits) ··· 1046 845 TXROT(7)); 1047 846 mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXSSZ(15), 1048 847 TXSSZ(0x0F)); 848 + mcasp_set_reg(mcasp, DAVINCI_MCASP_TXMASK_REG, mask); 1049 849 } 1050 - 1051 - mcasp_set_reg(mcasp, DAVINCI_MCASP_TXMASK_REG, mask); 1052 850 1053 851 return 0; 1054 852 } ··· 1059 859 int i; 1060 860 u8 tx_ser = 0; 1061 861 u8 rx_ser = 0; 1062 - u8 slots = mcasp->tdm_slots; 862 + int slots; 1063 863 u8 max_active_serializers, max_rx_serializers, max_tx_serializers; 1064 864 int active_serializers, numevt; 1065 865 u32 reg; 866 + 867 + slots = mcasp_get_tdm_slots(mcasp, stream); 1066 868 1067 869 /* In DIT mode we only allow maximum of one serializers for now */ 1068 870 if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE) ··· 1193 991 u32 mask = 0; 1194 992 u32 busel = 0; 1195 993 1196 - total_slots = mcasp->tdm_slots; 994 + total_slots = mcasp_get_tdm_slots(mcasp, stream); 1197 995 1198 996 /* 1199 997 * If more than one serializer is needed, then use them with ··· 1224 1022 mask |= (1 << i); 1225 1023 } 1226 1024 1227 - mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, TX_ASYNC); 1025 + if (mcasp->async_mode) 1026 + mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, TX_ASYNC); 1027 + else 1028 + mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, TX_ASYNC); 1228 1029 1229 1030 if (!mcasp->dat_port) 1230 1031 busel = TXSEL; ··· 1247 1042 * not running already we need to configure the TX slots in 1248 1043 * order to have correct FSX on the bus 1249 1044 */ 1250 - if (mcasp_is_synchronous(mcasp) && !mcasp->channels) 1045 + if (mcasp_is_frame_producer(mcasp) && mcasp_is_synchronous(mcasp) && 1046 + !mcasp->channels) 1251 1047 mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, 1252 1048 FSXMOD(total_slots), FSXMOD(0x1FF)); 1253 1049 } ··· 1326 1120 1327 1121 static int davinci_mcasp_calc_clk_div(struct davinci_mcasp *mcasp, 1328 1122 unsigned int sysclk_freq, 1329 - unsigned int bclk_freq, bool set) 1123 + unsigned int bclk_freq, 1124 + int stream, 1125 + bool set) 1330 1126 { 1331 - u32 reg = mcasp_get_reg(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG); 1332 1127 int div = sysclk_freq / bclk_freq; 1333 1128 int rem = sysclk_freq % bclk_freq; 1334 1129 int error_ppm; 1335 1130 int aux_div = 1; 1131 + int bclk_div_id, auxclk_div_id; 1132 + bool auxclk_enabled; 1133 + 1134 + if (mcasp->async_mode && stream == SNDRV_PCM_STREAM_CAPTURE) { 1135 + auxclk_enabled = mcasp_get_reg(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG) & AHCLKRE; 1136 + bclk_div_id = MCASP_CLKDIV_BCLK_RXONLY; 1137 + auxclk_div_id = MCASP_CLKDIV_AUXCLK_RXONLY; 1138 + } else if (mcasp->async_mode && stream == SNDRV_PCM_STREAM_PLAYBACK) { 1139 + auxclk_enabled = mcasp_get_reg(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG) & AHCLKXE; 1140 + bclk_div_id = MCASP_CLKDIV_BCLK_TXONLY; 1141 + auxclk_div_id = MCASP_CLKDIV_AUXCLK_TXONLY; 1142 + } else { 1143 + auxclk_enabled = mcasp_get_reg(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG) & AHCLKXE; 1144 + bclk_div_id = MCASP_CLKDIV_BCLK; 1145 + auxclk_div_id = MCASP_CLKDIV_AUXCLK; 1146 + } 1336 1147 1337 1148 if (div > (ACLKXDIV_MASK + 1)) { 1338 - if (reg & AHCLKXE) { 1149 + if (auxclk_enabled) { 1339 1150 aux_div = div / (ACLKXDIV_MASK + 1); 1340 1151 if (div % (ACLKXDIV_MASK + 1)) 1341 1152 aux_div++; ··· 1382 1159 dev_info(mcasp->dev, "Sample-rate is off by %d PPM\n", 1383 1160 error_ppm); 1384 1161 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); 1162 + __davinci_mcasp_set_clkdiv(mcasp, bclk_div_id, div, false); 1163 + if (auxclk_enabled) 1164 + __davinci_mcasp_set_clkdiv(mcasp, auxclk_div_id, 1165 + aux_div, false); 1389 1166 } 1390 1167 1391 1168 return error_ppm; ··· 1436 1213 int channels = params_channels(params); 1437 1214 int period_size = params_period_size(params); 1438 1215 int ret; 1216 + unsigned int sysclk_freq = mcasp_get_sysclk_freq(mcasp, substream->stream); 1439 1217 1440 1218 switch (params_format(params)) { 1441 1219 case SNDRV_PCM_FORMAT_U8: ··· 1477 1253 * If mcasp is BCLK master, and a BCLK divider was not provided by 1478 1254 * the machine driver, we need to calculate the ratio. 1479 1255 */ 1480 - if (mcasp->bclk_master && mcasp->bclk_div == 0 && mcasp->sysclk_freq) { 1481 - int slots = mcasp->tdm_slots; 1256 + if (mcasp->bclk_master && mcasp_get_bclk_div(mcasp, substream->stream) == 0 && 1257 + sysclk_freq) { 1258 + int slots, slot_width; 1482 1259 int rate = params_rate(params); 1483 1260 int sbits = params_width(params); 1484 1261 unsigned int bclk_target; 1485 1262 1486 - if (mcasp->slot_width) 1487 - sbits = mcasp->slot_width; 1263 + slots = mcasp_get_tdm_slots(mcasp, substream->stream); 1264 + 1265 + slot_width = mcasp_get_slot_width(mcasp, substream->stream); 1266 + if (slot_width) 1267 + sbits = slot_width; 1488 1268 1489 1269 if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE) 1490 1270 bclk_target = rate * sbits * slots; 1491 1271 else 1492 1272 bclk_target = rate * 128; 1493 1273 1494 - davinci_mcasp_calc_clk_div(mcasp, mcasp->sysclk_freq, 1495 - bclk_target, true); 1274 + davinci_mcasp_calc_clk_div(mcasp, sysclk_freq, 1275 + bclk_target, substream->stream, true); 1496 1276 } 1497 1277 1498 1278 ret = mcasp_common_hw_param(mcasp, substream->stream, ··· 1513 1285 if (ret) 1514 1286 return ret; 1515 1287 1516 - davinci_config_channel_size(mcasp, word_length); 1288 + davinci_config_channel_size(mcasp, word_length, substream->stream); 1517 1289 1518 - if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE) { 1290 + /* Channel constraints are disabled for async mode */ 1291 + if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE && !mcasp->async_mode) { 1519 1292 mcasp->channels = channels; 1520 1293 if (!mcasp->max_format_width) 1521 1294 mcasp->max_format_width = word_length; ··· 1560 1331 snd_pcm_format_t i; 1561 1332 1562 1333 snd_mask_none(&nfmt); 1563 - slot_width = rd->mcasp->slot_width; 1334 + slot_width = mcasp_get_slot_width(rd->mcasp, rd->stream); 1564 1335 1565 1336 pcm_for_each_format(i) { 1566 1337 if (snd_mask_test_format(fmt, i)) { ··· 1610 1381 struct snd_interval *ri = 1611 1382 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); 1612 1383 int sbits = params_width(params); 1613 - int slots = rd->mcasp->tdm_slots; 1384 + int slots, slot_width; 1614 1385 struct snd_interval range; 1615 1386 int i; 1616 1387 1617 - if (rd->mcasp->slot_width) 1618 - sbits = rd->mcasp->slot_width; 1388 + slots = mcasp_get_tdm_slots(rd->mcasp, rd->stream); 1389 + 1390 + slot_width = mcasp_get_slot_width(rd->mcasp, rd->stream); 1391 + if (slot_width) 1392 + sbits = slot_width; 1619 1393 1620 1394 snd_interval_any(&range); 1621 1395 range.empty = 1; ··· 1628 1396 uint bclk_freq = sbits * slots * 1629 1397 davinci_mcasp_dai_rates[i]; 1630 1398 unsigned int sysclk_freq; 1399 + unsigned int ratio; 1631 1400 int ppm; 1632 1401 1633 - if (rd->mcasp->auxclk_fs_ratio) 1634 - sysclk_freq = davinci_mcasp_dai_rates[i] * 1635 - rd->mcasp->auxclk_fs_ratio; 1402 + ratio = mcasp_get_auxclk_fs_ratio(rd->mcasp, rd->stream); 1403 + if (ratio) 1404 + sysclk_freq = davinci_mcasp_dai_rates[i] * ratio; 1636 1405 else 1637 - sysclk_freq = rd->mcasp->sysclk_freq; 1406 + sysclk_freq = mcasp_get_sysclk_freq(rd->mcasp, rd->stream); 1638 1407 1639 1408 ppm = davinci_mcasp_calc_clk_div(rd->mcasp, sysclk_freq, 1640 - bclk_freq, false); 1409 + bclk_freq, rd->stream, false); 1641 1410 if (abs(ppm) < DAVINCI_MAX_RATE_ERROR_PPM) { 1642 1411 if (range.empty) { 1643 1412 range.min = davinci_mcasp_dai_rates[i]; ··· 1664 1431 struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); 1665 1432 struct snd_mask nfmt; 1666 1433 int rate = params_rate(params); 1667 - int slots = rd->mcasp->tdm_slots; 1434 + int slots; 1668 1435 int count = 0; 1669 1436 snd_pcm_format_t i; 1437 + 1438 + slots = mcasp_get_tdm_slots(rd->mcasp, rd->stream); 1670 1439 1671 1440 snd_mask_none(&nfmt); 1672 1441 ··· 1676 1441 if (snd_mask_test_format(fmt, i)) { 1677 1442 uint sbits = snd_pcm_format_width(i); 1678 1443 unsigned int sysclk_freq; 1679 - int ppm; 1444 + unsigned int ratio; 1445 + int ppm, slot_width; 1680 1446 1681 - if (rd->mcasp->auxclk_fs_ratio) 1682 - sysclk_freq = rate * 1683 - rd->mcasp->auxclk_fs_ratio; 1447 + ratio = mcasp_get_auxclk_fs_ratio(rd->mcasp, rd->stream); 1448 + if (ratio) 1449 + sysclk_freq = rate * ratio; 1684 1450 else 1685 - sysclk_freq = rd->mcasp->sysclk_freq; 1451 + sysclk_freq = mcasp_get_sysclk_freq(rd->mcasp, rd->stream); 1686 1452 1687 - if (rd->mcasp->slot_width) 1688 - sbits = rd->mcasp->slot_width; 1453 + slot_width = mcasp_get_slot_width(rd->mcasp, rd->stream); 1454 + if (slot_width) 1455 + sbits = slot_width; 1689 1456 1690 1457 ppm = davinci_mcasp_calc_clk_div(rd->mcasp, sysclk_freq, 1691 1458 sbits * slots * rate, 1692 - false); 1459 + rd->stream, false); 1693 1460 if (abs(ppm) < DAVINCI_MAX_RATE_ERROR_PPM) { 1694 1461 snd_mask_set_format(&nfmt, i); 1695 1462 count++; ··· 1728 1491 &mcasp->ruledata[substream->stream]; 1729 1492 u32 max_channels = 0; 1730 1493 int i, dir, ret; 1731 - int tdm_slots = mcasp->tdm_slots; 1494 + int tdm_slots; 1732 1495 u8 *numevt; 1733 1496 1734 1497 /* Do not allow more then one stream per direction */ ··· 1736 1499 return -EBUSY; 1737 1500 1738 1501 mcasp->substreams[substream->stream] = substream; 1502 + 1503 + tdm_slots = mcasp_get_tdm_slots(mcasp, substream->stream); 1739 1504 1740 1505 if (mcasp->tdm_mask[substream->stream]) 1741 1506 tdm_slots = hweight32(mcasp->tdm_mask[substream->stream]); ··· 1760 1521 } 1761 1522 ruledata->serializers = max_channels; 1762 1523 ruledata->mcasp = mcasp; 1524 + ruledata->stream = substream->stream; 1763 1525 max_channels *= tdm_slots; 1764 1526 /* 1765 1527 * If the already active stream has less channels than the calculated ··· 1768 1528 * is in use we need to use that as a constraint for the second stream. 1769 1529 * Otherwise (first stream or less allowed channels or more than one 1770 1530 * serializer in use) we use the calculated constraint. 1531 + * 1532 + * However, in async mode, TX and RX have independent clocks and can 1533 + * use different configurations, so don't apply the constraint. 1771 1534 */ 1772 1535 if (mcasp->channels && mcasp->channels < max_channels && 1773 - ruledata->serializers == 1) 1536 + ruledata->serializers == 1 && 1537 + !mcasp->async_mode) 1774 1538 max_channels = mcasp->channels; 1775 1539 /* 1776 1540 * But we can always allow channels upto the amount of ··· 1791 1547 0, SNDRV_PCM_HW_PARAM_CHANNELS, 1792 1548 &mcasp->chconstr[substream->stream]); 1793 1549 1794 - if (mcasp->max_format_width) { 1550 + if (mcasp->max_format_width && !mcasp->async_mode) { 1795 1551 /* 1796 1552 * Only allow formats which require same amount of bits on the 1797 - * bus as the currently running stream 1553 + * bus as the currently running stream to ensure sync mode 1798 1554 */ 1799 1555 ret = snd_pcm_hw_rule_add(substream->runtime, 0, 1800 1556 SNDRV_PCM_HW_PARAM_FORMAT, ··· 1803 1559 SNDRV_PCM_HW_PARAM_FORMAT, -1); 1804 1560 if (ret) 1805 1561 return ret; 1806 - } 1807 - else if (mcasp->slot_width) { 1562 + } else if (mcasp_get_slot_width(mcasp, substream->stream)) { 1808 1563 /* Only allow formats require <= slot_width bits on the bus */ 1809 1564 ret = snd_pcm_hw_rule_add(substream->runtime, 0, 1810 1565 SNDRV_PCM_HW_PARAM_FORMAT, ··· 1818 1575 * If we rely on implicit BCLK divider setting we should 1819 1576 * set constraints based on what we can provide. 1820 1577 */ 1821 - if (mcasp->bclk_master && mcasp->bclk_div == 0 && mcasp->sysclk_freq) { 1578 + if (mcasp->bclk_master && mcasp_get_bclk_div(mcasp, substream->stream) == 0 && 1579 + mcasp_get_sysclk_freq(mcasp, substream->stream)) { 1822 1580 ret = snd_pcm_hw_rule_add(substream->runtime, 0, 1823 1581 SNDRV_PCM_HW_PARAM_RATE, 1824 1582 davinci_mcasp_hw_rule_rate, ··· 1996 1752 .formats = DAVINCI_MCASP_PCM_FMTS, 1997 1753 }, 1998 1754 .ops = &davinci_mcasp_dai_ops, 1999 - 2000 - .symmetric_rate = 1, 2001 1755 }, 2002 1756 { 2003 1757 .name = "davinci-mcasp.1", ··· 2153 1911 goto out; 2154 1912 } 2155 1913 1914 + /* Parse TX-specific TDM slot and use it as default for RX */ 2156 1915 if (of_property_read_u32(np, "tdm-slots", &val) == 0) { 2157 1916 if (val < 2 || val > 32) { 2158 - dev_err(&pdev->dev, "tdm-slots must be in rage [2-32]\n"); 1917 + dev_err(&pdev->dev, "tdm-slots must be in range [2-32]\n"); 2159 1918 return -EINVAL; 2160 1919 } 2161 1920 2162 - pdata->tdm_slots = val; 1921 + pdata->tdm_slots_tx = val; 1922 + pdata->tdm_slots_rx = val; 2163 1923 } else if (pdata->op_mode == DAVINCI_MCASP_IIS_MODE) { 2164 1924 mcasp->missing_audio_param = true; 2165 1925 goto out; 2166 1926 } 1927 + 1928 + /* Parse RX-specific TDM slot count if provided */ 1929 + if (of_property_read_u32(np, "tdm-slots-rx", &val) == 0) { 1930 + if (val < 2 || val > 32) { 1931 + dev_err(&pdev->dev, "tdm-slots-rx must be in range [2-32]\n"); 1932 + return -EINVAL; 1933 + } 1934 + 1935 + pdata->tdm_slots_rx = val; 1936 + } 1937 + 1938 + if (pdata->op_mode != DAVINCI_MCASP_DIT_MODE) 1939 + mcasp->async_mode = of_property_read_bool(np, "ti,async-mode"); 2167 1940 2168 1941 of_serial_dir32 = of_get_property(np, "serial-dir", &val); 2169 1942 val /= sizeof(u32); ··· 2205 1948 if (of_property_read_u32(np, "rx-num-evt", &val) == 0) 2206 1949 pdata->rxnumevt = val; 2207 1950 2208 - if (of_property_read_u32(np, "auxclk-fs-ratio", &val) == 0) 2209 - mcasp->auxclk_fs_ratio = val; 1951 + /* Parse TX-specific auxclk/fs ratio and use it as default for RX */ 1952 + if (of_property_read_u32(np, "auxclk-fs-ratio", &val) == 0) { 1953 + mcasp->auxclk_fs_ratio_tx = val; 1954 + mcasp->auxclk_fs_ratio_rx = val; 1955 + } 1956 + 1957 + /* Parse RX-specific auxclk/fs ratio if provided */ 1958 + if (of_property_read_u32(np, "auxclk-fs-ratio-rx", &val) == 0) 1959 + mcasp->auxclk_fs_ratio_rx = val; 2210 1960 2211 1961 if (of_property_read_u32(np, "dismod", &val) == 0) { 2212 1962 if (val == 0 || val == 2 || val == 3) { ··· 2242 1978 mcasp->op_mode = pdata->op_mode; 2243 1979 /* sanity check for tdm slots parameter */ 2244 1980 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; 1981 + if (pdata->tdm_slots_tx < 2) { 1982 + dev_warn(&pdev->dev, "invalid tdm tx slots: %d\n", 1983 + pdata->tdm_slots_tx); 1984 + mcasp->tdm_slots_tx = 2; 1985 + } else if (pdata->tdm_slots_tx > 32) { 1986 + dev_warn(&pdev->dev, "invalid tdm tx slots: %d\n", 1987 + pdata->tdm_slots_tx); 1988 + mcasp->tdm_slots_tx = 32; 2253 1989 } else { 2254 - mcasp->tdm_slots = pdata->tdm_slots; 1990 + mcasp->tdm_slots_tx = pdata->tdm_slots_tx; 1991 + } 1992 + 1993 + if (pdata->tdm_slots_rx < 2) { 1994 + dev_warn(&pdev->dev, "invalid tdm rx slots: %d\n", 1995 + pdata->tdm_slots_rx); 1996 + mcasp->tdm_slots_rx = 2; 1997 + } else if (pdata->tdm_slots_rx > 32) { 1998 + dev_warn(&pdev->dev, "invalid tdm rx slots: %d\n", 1999 + pdata->tdm_slots_rx); 2000 + mcasp->tdm_slots_rx = 32; 2001 + } else { 2002 + mcasp->tdm_slots_rx = pdata->tdm_slots_rx; 2255 2003 } 2256 2004 } else { 2257 - mcasp->tdm_slots = 32; 2005 + mcasp->tdm_slots_tx = 32; 2006 + mcasp->tdm_slots_rx = 32; 2007 + } 2008 + 2009 + /* Different TX/RX slot counts require async mode */ 2010 + if (pdata->op_mode != DAVINCI_MCASP_DIT_MODE && 2011 + mcasp->tdm_slots_tx != mcasp->tdm_slots_rx && !mcasp->async_mode) { 2012 + dev_err(&pdev->dev, 2013 + "Different TX (%d) and RX (%d) TDM slots require ti,async-mode\n", 2014 + mcasp->tdm_slots_tx, mcasp->tdm_slots_rx); 2015 + return -EINVAL; 2016 + } 2017 + 2018 + /* Different TX/RX auxclk-fs-ratio require async mode */ 2019 + if (pdata->op_mode != DAVINCI_MCASP_DIT_MODE && 2020 + mcasp->auxclk_fs_ratio_tx && mcasp->auxclk_fs_ratio_rx && 2021 + mcasp->auxclk_fs_ratio_tx != mcasp->auxclk_fs_ratio_rx && !mcasp->async_mode) { 2022 + dev_err(&pdev->dev, 2023 + "Different TX (%d) and RX (%d) auxclk-fs-ratio require ti,async-mode\n", 2024 + mcasp->auxclk_fs_ratio_tx, mcasp->auxclk_fs_ratio_rx); 2025 + return -EINVAL; 2258 2026 } 2259 2027 2260 2028 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 */