| @@ -71,6 +71,7 @@ struct davinci_mcasp_context { · 70 unmodified lines |
| 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 { |
| @@ -88,21 +89,27 @@ struct davinci_mcasp { · 11 unmodified lines |
| 88 | 89 | bool missing_audio_param; |
| 89 | 90 | |
| 90 | 91 | /* McASP specific data */ |
| 91 | | − int tdm_slots; |
| 92 | + int tdm_slots_tx; |
| 93 | + int tdm_slots_rx; |
| 92 | 94 | u32 tdm_mask[2]; |
| 93 | | − int slot_width; |
| 95 | + int slot_width_tx; |
| 96 | + int slot_width_rx; |
| 94 | 97 | u8 op_mode; |
| 95 | 98 | u8 dismod; |
| 96 | 99 | u8 num_serializer; |
| 97 | 100 | u8 *serial_dir; |
| 98 | 101 | u8 version; |
| 99 | | − u8 bclk_div; |
| 102 | + u8 bclk_div_tx; |
| 103 | + u8 bclk_div_rx; |
| 100 | 104 | int streams; |
| 101 | 105 | u32 irq_request[2]; |
| 102 | 106 | |
| 103 | | − int sysclk_freq; |
| 107 | + unsigned int sysclk_freq_tx; |
| 108 | + unsigned int sysclk_freq_rx; |
| 104 | 109 | bool bclk_master; |
| 105 | | − u32 auxclk_fs_ratio; |
| 110 | + bool async_mode; |
| 111 | + u32 auxclk_fs_ratio_tx; |
| 112 | + u32 auxclk_fs_ratio_rx; |
| 106 | 113 | |
| 107 | 114 | unsigned long pdir; /* Pin direction bitfield */ |
| 108 | 115 | |
| @@ -204,6 +211,27 @@ static inline void mcasp_set_clk_pdir(struct davinci_mcasp *mcasp, bool enable) · 95 unmodified lines |
| 204 | 211 | } |
| 205 | 212 | } |
| 206 | 213 | |
| 214 | +static inline void mcasp_set_clk_pdir_stream(struct davinci_mcasp *mcasp, |
| 215 | + int stream, bool enable) |
| 216 | +{ |
| 217 | + u32 bit, bit_end; |
| 218 | + |
| 219 | + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { |
| 220 | + bit = PIN_BIT_ACLKX; |
| 221 | + bit_end = PIN_BIT_AFSX + 1; |
| 222 | + } else { |
| 223 | + bit = PIN_BIT_ACLKR; |
| 224 | + bit_end = PIN_BIT_AFSR + 1; |
| 225 | + } |
| 226 | + |
| 227 | + for_each_set_bit_from(bit, &mcasp->pdir, bit_end) { |
| 228 | + if (enable) |
| 229 | + mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(bit)); |
| 230 | + else |
| 231 | + mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(bit)); |
| 232 | + } |
| 233 | +} |
| 234 | + |
| 207 | 235 | static inline void mcasp_set_axr_pdir(struct davinci_mcasp *mcasp, bool enable) |
| 208 | 236 | { |
| 209 | 237 | u32 bit; |
| @@ -216,6 +244,36 @@ static inline void mcasp_set_axr_pdir(struct davinci_mcasp *mcasp, bool enable) · 6 unmodified lines |
| 216 | 244 | } |
| 217 | 245 | } |
| 218 | 246 | |
| 247 | +static inline int mcasp_get_tdm_slots(struct davinci_mcasp *mcasp, int stream) |
| 248 | +{ |
| 249 | + return (stream == SNDRV_PCM_STREAM_PLAYBACK) ? |
| 250 | + mcasp->tdm_slots_tx : mcasp->tdm_slots_rx; |
| 251 | +} |
| 252 | + |
| 253 | +static inline int mcasp_get_slot_width(struct davinci_mcasp *mcasp, int stream) |
| 254 | +{ |
| 255 | + return (stream == SNDRV_PCM_STREAM_PLAYBACK) ? |
| 256 | + mcasp->slot_width_tx : mcasp->slot_width_rx; |
| 257 | +} |
| 258 | + |
| 259 | +static inline unsigned int mcasp_get_sysclk_freq(struct davinci_mcasp *mcasp, int stream) |
| 260 | +{ |
| 261 | + return (stream == SNDRV_PCM_STREAM_PLAYBACK) ? |
| 262 | + mcasp->sysclk_freq_tx : mcasp->sysclk_freq_rx; |
| 263 | +} |
| 264 | + |
| 265 | +static inline unsigned int mcasp_get_bclk_div(struct davinci_mcasp *mcasp, int stream) |
| 266 | +{ |
| 267 | + return (stream == SNDRV_PCM_STREAM_PLAYBACK) ? |
| 268 | + mcasp->bclk_div_tx : mcasp->bclk_div_rx; |
| 269 | +} |
| 270 | + |
| 271 | +static inline unsigned int mcasp_get_auxclk_fs_ratio(struct davinci_mcasp *mcasp, int stream) |
| 272 | +{ |
| 273 | + return (stream == SNDRV_PCM_STREAM_PLAYBACK) ? |
| 274 | + mcasp->auxclk_fs_ratio_tx : mcasp->auxclk_fs_ratio_rx; |
| 275 | +} |
| 276 | + |
| 219 | 277 | static void mcasp_start_rx(struct davinci_mcasp *mcasp) |
| 220 | 278 | { |
| 221 | 279 | if (mcasp->rxnumevt) { /* enable FIFO */ |
| @@ -231,13 +289,17 @@ static void mcasp_start_rx(struct davinci_mcasp *mcasp) · 9 unmodified lines |
| 231 | 289 | /* |
| 232 | 290 | * When ASYNC == 0 the transmit and receive sections operate |
| 233 | 291 | * synchronously from the transmit clock and frame sync. We need to make |
| 234 | | − * sure that the TX signlas are enabled when starting reception. |
| 292 | + * sure that the TX signals are enabled when starting reception, |
| 293 | + * when the McASP is the producer. |
| 235 | 294 | */ |
| 236 | 295 | if (mcasp_is_frame_producer(mcasp) && mcasp_is_synchronous(mcasp)) { |
| 237 | 296 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST); |
| 238 | 297 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST); |
| 239 | 298 | } |
| 240 | | − mcasp_set_clk_pdir(mcasp, true); |
| 299 | + if (mcasp_is_synchronous(mcasp)) |
| 300 | + mcasp_set_clk_pdir(mcasp, true); |
| 301 | + else |
| 302 | + mcasp_set_clk_pdir_stream(mcasp, SNDRV_PCM_STREAM_CAPTURE, true); |
| 241 | 303 | |
| 242 | 304 | /* Activate serializer(s) */ |
| 243 | 305 | mcasp_set_reg(mcasp, DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF); |
| @@ -268,7 +330,10 @@ static void mcasp_start_tx(struct davinci_mcasp *mcasp) · 24 unmodified lines |
| 268 | 330 | /* Start clocks */ |
| 269 | 331 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST); |
| 270 | 332 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST); |
| 271 | | − mcasp_set_clk_pdir(mcasp, true); |
| 333 | + if (mcasp_is_synchronous(mcasp)) |
| 334 | + mcasp_set_clk_pdir(mcasp, true); |
| 335 | + else |
| 336 | + mcasp_set_clk_pdir_stream(mcasp, SNDRV_PCM_STREAM_PLAYBACK, true); |
| 272 | 337 | |
| 273 | 338 | /* Activate serializer(s) */ |
| 274 | 339 | mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF); |
| @@ -311,9 +376,17 @@ static void mcasp_stop_rx(struct davinci_mcasp *mcasp) · 36 unmodified lines |
| 311 | 376 | /* |
| 312 | 377 | * In synchronous mode stop the TX clocks if no other stream is |
| 313 | 378 | * running |
| 379 | + * Otherwise in async mode only stop RX clocks |
| 314 | 380 | */ |
| 315 | | − if (!mcasp->streams) |
| 381 | + if (mcasp_is_synchronous(mcasp) && !mcasp->streams) |
| 316 | 382 | mcasp_set_clk_pdir(mcasp, false); |
| 383 | + else if (!mcasp_is_synchronous(mcasp)) |
| 384 | + mcasp_set_clk_pdir_stream(mcasp, SNDRV_PCM_STREAM_CAPTURE, false); |
| 385 | + /* |
| 386 | + * When McASP is the producer and operating in synchronous mode, |
| 387 | + * stop the transmit clocks if no other stream is running. As |
| 388 | + * tx & rx operate synchronously from the transmit clock. |
| 389 | + */ |
| 317 | 390 | if (mcasp_is_frame_producer(mcasp) && mcasp_is_synchronous(mcasp) && !mcasp->streams) |
| 318 | 391 | mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, 0); |
| 319 | 392 | |
| @@ -338,11 +411,14 @@ static void mcasp_stop_tx(struct davinci_mcasp *mcasp) · 18 unmodified lines |
| 338 | 411 | /* |
| 339 | 412 | * In synchronous mode keep TX clocks running if the capture stream is |
| 340 | 413 | * still running. |
| 414 | + * Otherwise in async mode only stop TX clocks |
| 341 | 415 | */ |
| 342 | 416 | if (mcasp_is_frame_producer(mcasp) && mcasp_is_synchronous(mcasp) && mcasp->streams) |
| 343 | 417 | val = TXHCLKRST | TXCLKRST | TXFSRST; |
| 344 | | − if (!mcasp->streams) |
| 418 | + if (mcasp_is_synchronous(mcasp) && !mcasp->streams) |
| 345 | 419 | mcasp_set_clk_pdir(mcasp, false); |
| 420 | + else if (!mcasp_is_synchronous(mcasp)) |
| 421 | + mcasp_set_clk_pdir_stream(mcasp, SNDRV_PCM_STREAM_PLAYBACK, false); |
| 346 | 422 | |
| 347 | 423 | |
| 348 | 424 | mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, val); |
| @@ -626,13 +702,39 @@ static int __davinci_mcasp_set_clkdiv(struct davinci_mcasp *mcasp, int div_id, · 277 unmodified lines |
| 626 | 702 | AHCLKRDIV(div - 1), AHCLKRDIV_MASK); |
| 627 | 703 | break; |
| 628 | 704 | |
| 705 | + case MCASP_CLKDIV_AUXCLK_TXONLY: /* MCLK divider for TX only */ |
| 706 | + mcasp_mod_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, |
| 707 | + AHCLKXDIV(div - 1), AHCLKXDIV_MASK); |
| 708 | + break; |
| 709 | + |
| 710 | + case MCASP_CLKDIV_AUXCLK_RXONLY: /* MCLK divider for RX only */ |
| 711 | + mcasp_mod_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, |
| 712 | + AHCLKRDIV(div - 1), AHCLKRDIV_MASK); |
| 713 | + break; |
| 714 | + |
| 629 | 715 | case MCASP_CLKDIV_BCLK: /* BCLK divider */ |
| 630 | 716 | mcasp_mod_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, |
| 631 | 717 | ACLKXDIV(div - 1), ACLKXDIV_MASK); |
| 718 | + mcasp_mod_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, |
| 719 | + ACLKRDIV(div - 1), ACLKRDIV_MASK); |
| 720 | + if (explicit) { |
| 721 | + mcasp->bclk_div_tx = div; |
| 722 | + mcasp->bclk_div_rx = div; |
| 723 | + } |
| 724 | + break; |
| 725 | + |
| 726 | + case MCASP_CLKDIV_BCLK_TXONLY: /* BCLK divider for TX only */ |
| 727 | + mcasp_mod_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, |
| 728 | + ACLKXDIV(div - 1), ACLKXDIV_MASK); |
| 729 | + if (explicit) |
| 730 | + mcasp->bclk_div_tx = div; |
| 731 | + break; |
| 732 | + |
| 733 | + case MCASP_CLKDIV_BCLK_RXONLY: /* BCLK divider for RX only */ |
| 632 | 734 | mcasp_mod_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, |
| 633 | 735 | ACLKRDIV(div - 1), ACLKRDIV_MASK); |
| 634 | 736 | if (explicit) |
| 635 | | − mcasp->bclk_div = div; |
| 737 | + mcasp->bclk_div_rx = div; |
| 636 | 738 | break; |
| 637 | 739 | |
| 638 | 740 | case MCASP_CLKDIV_BCLK_FS_RATIO: |
| @@ -646,11 +748,33 @@ static int __davinci_mcasp_set_clkdiv(struct davinci_mcasp *mcasp, int div_id, · 7 unmodified lines |
| 646 | 748 | * tdm_slot width by dividing the ratio by the |
| 647 | 749 | * number of configured tdm slots. |
| 648 | 750 | */ |
| 649 | | − mcasp->slot_width = div / mcasp->tdm_slots; |
| 650 | | − if (div % mcasp->tdm_slots) |
| 751 | + mcasp->slot_width_tx = div / mcasp->tdm_slots_tx; |
| 752 | + if (div % mcasp->tdm_slots_tx) |
| 651 | 753 | dev_warn(mcasp->dev, |
| 652 | | − "%s(): BCLK/LRCLK %d is not divisible by %d tdm slots", |
| 653 | | − __func__, div, mcasp->tdm_slots); |
| 754 | + "%s(): BCLK/LRCLK %d is not divisible by %d tx tdm slots", |
| 755 | + __func__, div, mcasp->tdm_slots_tx); |
| 756 | + |
| 757 | + mcasp->slot_width_rx = div / mcasp->tdm_slots_rx; |
| 758 | + if (div % mcasp->tdm_slots_rx) |
| 759 | + dev_warn(mcasp->dev, |
| 760 | + "%s(): BCLK/LRCLK %d is not divisible by %d rx tdm slots", |
| 761 | + __func__, div, mcasp->tdm_slots_rx); |
| 762 | + break; |
| 763 | + |
| 764 | + case MCASP_CLKDIV_BCLK_FS_RATIO_TXONLY: |
| 765 | + mcasp->slot_width_tx = div / mcasp->tdm_slots_tx; |
| 766 | + if (div % mcasp->tdm_slots_tx) |
| 767 | + dev_warn(mcasp->dev, |
| 768 | + "%s(): BCLK/LRCLK %d is not divisible by %d tx tdm slots", |
| 769 | + __func__, div, mcasp->tdm_slots_tx); |
| 770 | + break; |
| 771 | + |
| 772 | + case MCASP_CLKDIV_BCLK_FS_RATIO_RXONLY: |
| 773 | + mcasp->slot_width_rx = div / mcasp->tdm_slots_rx; |
| 774 | + if (div % mcasp->tdm_slots_rx) |
| 775 | + dev_warn(mcasp->dev, |
| 776 | + "%s(): BCLK/LRCLK %d is not divisible by %d rx tdm slots", |
| 777 | + __func__, div, mcasp->tdm_slots_rx); |
| 654 | 778 | break; |
| 655 | 779 | |
| 656 | 780 | default: |
| @@ -684,6 +808,20 @@ static int davinci_mcasp_set_sysclk(struct snd_soc_dai *dai, int clk_id, · 27 unmodified lines |
| 684 | 808 | mcasp_clr_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, |
| 685 | 809 | AHCLKRE); |
| 686 | 810 | clear_bit(PIN_BIT_AHCLKX, &mcasp->pdir); |
| 811 | + mcasp->sysclk_freq_tx = freq; |
| 812 | + mcasp->sysclk_freq_rx = freq; |
| 813 | + break; |
| 814 | + case MCASP_CLK_HCLK_AHCLK_TXONLY: |
| 815 | + mcasp_clr_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, |
| 816 | + AHCLKXE); |
| 817 | + clear_bit(PIN_BIT_AHCLKX, &mcasp->pdir); |
| 818 | + mcasp->sysclk_freq_tx = freq; |
| 819 | + break; |
| 820 | + case MCASP_CLK_HCLK_AHCLK_RXONLY: |
| 821 | + mcasp_clr_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, |
| 822 | + AHCLKRE); |
| 823 | + clear_bit(PIN_BIT_AHCLKR, &mcasp->pdir); |
| 824 | + mcasp->sysclk_freq_rx = freq; |
| 687 | 825 | break; |
| 688 | 826 | case MCASP_CLK_HCLK_AUXCLK: |
| 689 | 827 | mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, |
| @@ -691,22 +829,56 @@ static int davinci_mcasp_set_sysclk(struct snd_soc_dai *dai, int clk_id, · 1 unmodified line |
| 691 | 829 | mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, |
| 692 | 830 | AHCLKRE); |
| 693 | 831 | set_bit(PIN_BIT_AHCLKX, &mcasp->pdir); |
| 832 | + mcasp->sysclk_freq_tx = freq; |
| 833 | + mcasp->sysclk_freq_rx = freq; |
| 834 | + break; |
| 835 | + case MCASP_CLK_HCLK_AUXCLK_TXONLY: |
| 836 | + mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, |
| 837 | + AHCLKXE); |
| 838 | + set_bit(PIN_BIT_AHCLKX, &mcasp->pdir); |
| 839 | + mcasp->sysclk_freq_tx = freq; |
| 840 | + break; |
| 841 | + case MCASP_CLK_HCLK_AUXCLK_RXONLY: |
| 842 | + mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, |
| 843 | + AHCLKRE); |
| 844 | + set_bit(PIN_BIT_AHCLKR, &mcasp->pdir); |
| 845 | + mcasp->sysclk_freq_rx = freq; |
| 694 | 846 | break; |
| 695 | 847 | default: |
| 696 | 848 | dev_err(mcasp->dev, "Invalid clk id: %d\n", clk_id); |
| 697 | 849 | goto out; |
| 698 | 850 | } |
| 699 | 851 | } else { |
| 700 | | − /* Select AUXCLK as HCLK */ |
| 701 | | − mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE); |
| 702 | | − mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, AHCLKRE); |
| 703 | | − set_bit(PIN_BIT_AHCLKX, &mcasp->pdir); |
| 852 | + /* McASP is clock master, select AUXCLK as HCLK */ |
| 853 | + switch (clk_id) { |
| 854 | + case MCASP_CLK_HCLK_AUXCLK_TXONLY: |
| 855 | + mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, |
| 856 | + AHCLKXE); |
| 857 | + set_bit(PIN_BIT_AHCLKX, &mcasp->pdir); |
| 858 | + mcasp->sysclk_freq_tx = freq; |
| 859 | + break; |
| 860 | + case MCASP_CLK_HCLK_AUXCLK_RXONLY: |
| 861 | + mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, |
| 862 | + AHCLKRE); |
| 863 | + set_bit(PIN_BIT_AHCLKR, &mcasp->pdir); |
| 864 | + mcasp->sysclk_freq_rx = freq; |
| 865 | + break; |
| 866 | + default: |
| 867 | + mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, |
| 868 | + AHCLKXE); |
| 869 | + mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, |
| 870 | + AHCLKRE); |
| 871 | + set_bit(PIN_BIT_AHCLKX, &mcasp->pdir); |
| 872 | + set_bit(PIN_BIT_AHCLKR, &mcasp->pdir); |
| 873 | + mcasp->sysclk_freq_tx = freq; |
| 874 | + mcasp->sysclk_freq_rx = freq; |
| 875 | + break; |
| 876 | + } |
| 704 | 877 | } |
| 705 | 878 | /* |
| 706 | 879 | * When AHCLK X/R is selected to be output it means that the HCLK is |
| 707 | 880 | * the same clock - coming via AUXCLK. |
| 708 | 881 | */ |
| 709 | | − mcasp->sysclk_freq = freq; |
| 710 | 882 | out: |
| 711 | 883 | pm_runtime_put(mcasp->dev); |
| 712 | 884 | return 0; |
| @@ -718,9 +890,11 @@ static int davinci_mcasp_ch_constraint(struct davinci_mcasp *mcasp, int stream, · 5 unmodified lines |
| 718 | 890 | { |
| 719 | 891 | struct snd_pcm_hw_constraint_list *cl = &mcasp->chconstr[stream]; |
| 720 | 892 | unsigned int *list = (unsigned int *) cl->list; |
| 721 | | − int slots = mcasp->tdm_slots; |
| 893 | + int slots; |
| 722 | 894 | int i, count = 0; |
| 723 | 895 | |
| 896 | + slots = mcasp_get_tdm_slots(mcasp, stream); |
| 897 | + |
| 724 | 898 | if (mcasp->tdm_mask[stream]) |
| 725 | 899 | slots = hweight32(mcasp->tdm_mask[stream]); |
| 726 | 900 | |
| @@ -785,27 +959,42 @@ static int davinci_mcasp_set_tdm_slot(struct snd_soc_dai *dai, · 58 unmodified lines |
| 785 | 959 | return -EINVAL; |
| 786 | 960 | } |
| 787 | 961 | |
| 788 | | − mcasp->tdm_slots = slots; |
| 962 | + if (mcasp->async_mode) { |
| 963 | + if (tx_mask) { |
| 964 | + mcasp->tdm_slots_tx = slots; |
| 965 | + mcasp->slot_width_tx = slot_width; |
| 966 | + } |
| 967 | + if (rx_mask) { |
| 968 | + mcasp->tdm_slots_rx = slots; |
| 969 | + mcasp->slot_width_rx = slot_width; |
| 970 | + } |
| 971 | + } else { |
| 972 | + mcasp->tdm_slots_tx = slots; |
| 973 | + mcasp->tdm_slots_rx = slots; |
| 974 | + mcasp->slot_width_tx = slot_width; |
| 975 | + mcasp->slot_width_rx = slot_width; |
| 976 | + } |
| 977 | + |
| 789 | 978 | mcasp->tdm_mask[SNDRV_PCM_STREAM_PLAYBACK] = tx_mask; |
| 790 | 979 | mcasp->tdm_mask[SNDRV_PCM_STREAM_CAPTURE] = rx_mask; |
| 791 | | − mcasp->slot_width = slot_width; |
| 792 | 980 | |
| 793 | 981 | return davinci_mcasp_set_ch_constraints(mcasp); |
| 794 | 982 | } |
| 795 | 983 | |
| 796 | 984 | static int davinci_config_channel_size(struct davinci_mcasp *mcasp, |
| 797 | | − int sample_width) |
| 985 | + int sample_width, int stream) |
| 798 | 986 | { |
| 799 | 987 | u32 fmt; |
| 800 | 988 | u32 tx_rotate, rx_rotate, slot_width; |
| 801 | 989 | u32 mask = (1ULL << sample_width) - 1; |
| 802 | 990 | |
| 803 | | − if (mcasp->slot_width) |
| 804 | | − slot_width = mcasp->slot_width; |
| 805 | | − else if (mcasp->max_format_width) |
| 806 | | − slot_width = mcasp->max_format_width; |
| 807 | | − else |
| 808 | | − slot_width = sample_width; |
| 991 | + slot_width = mcasp_get_slot_width(mcasp, stream); |
| 992 | + if (!slot_width) { |
| 993 | + if (mcasp->max_format_width) |
| 994 | + slot_width = mcasp->max_format_width; |
| 995 | + else |
| 996 | + slot_width = sample_width; |
| 997 | + } |
| 809 | 998 | /* |
| 810 | 999 | * TX rotation: |
| 811 | 1000 | * right aligned formats: rotate w/ slot_width |
| @@ -828,17 +1017,23 @@ static int davinci_config_channel_size(struct davinci_mcasp *mcasp, · 16 unmodified lines |
| 828 | 1017 | fmt = (slot_width >> 1) - 1; |
| 829 | 1018 | |
| 830 | 1019 | if (mcasp->op_mode != DAVINCI_MCASP_DIT_MODE) { |
| 831 | | − mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, RXSSZ(fmt), |
| 832 | | − RXSSZ(0x0F)); |
| 833 | | − mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXSSZ(fmt), |
| 834 | | − TXSSZ(0x0F)); |
| 835 | | − mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXROT(tx_rotate), |
| 836 | | − TXROT(7)); |
| 837 | | − mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, RXROT(rx_rotate), |
| 838 | | − RXROT(7)); |
| 839 | | − mcasp_set_reg(mcasp, DAVINCI_MCASP_RXMASK_REG, mask); |
| 1020 | + if (!mcasp->async_mode || stream == SNDRV_PCM_STREAM_PLAYBACK) { |
| 1021 | + mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXSSZ(fmt), |
| 1022 | + TXSSZ(0x0F)); |
| 1023 | + mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXROT(tx_rotate), |
| 1024 | + TXROT(7)); |
| 1025 | + mcasp_set_reg(mcasp, DAVINCI_MCASP_TXMASK_REG, mask); |
| 1026 | + } |
| 1027 | + if (!mcasp->async_mode || stream == SNDRV_PCM_STREAM_CAPTURE) { |
| 1028 | + mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, RXSSZ(fmt), |
| 1029 | + RXSSZ(0x0F)); |
| 1030 | + mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, RXROT(rx_rotate), |
| 1031 | + RXROT(7)); |
| 1032 | + mcasp_set_reg(mcasp, DAVINCI_MCASP_RXMASK_REG, mask); |
| 1033 | + } |
| 840 | 1034 | } else { |
| 841 | 1035 | /* |
| 1036 | + * DIT mode only use TX serializers |
| 842 | 1037 | * according to the TRM it should be TXROT=0, this one works: |
| 843 | 1038 | * 16 bit to 23-8 (TXROT=6, rotate 24 bits) |
| 844 | 1039 | * 24 bit to 23-0 (TXROT=0, rotate 0 bits) |
| @@ -851,10 +1046,9 @@ static int davinci_config_channel_size(struct davinci_mcasp *mcasp, · 6 unmodified lines |
| 851 | 1046 | TXROT(7)); |
| 852 | 1047 | mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXSSZ(15), |
| 853 | 1048 | TXSSZ(0x0F)); |
| 1049 | + mcasp_set_reg(mcasp, DAVINCI_MCASP_TXMASK_REG, mask); |
| 854 | 1050 | } |
| 855 | 1051 | |
| 856 | | − mcasp_set_reg(mcasp, DAVINCI_MCASP_TXMASK_REG, mask); |
| 857 | | − |
| 858 | 1052 | return 0; |
| 859 | 1053 | } |
| 860 | 1054 | |
| @@ -865,11 +1059,13 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, · 4 unmodified lines |
| 865 | 1059 | int i; |
| 866 | 1060 | u8 tx_ser = 0; |
| 867 | 1061 | u8 rx_ser = 0; |
| 868 | | − u8 slots = mcasp->tdm_slots; |
| 1062 | + int slots; |
| 869 | 1063 | u8 max_active_serializers, max_rx_serializers, max_tx_serializers; |
| 870 | 1064 | int active_serializers, numevt; |
| 871 | 1065 | u32 reg; |
| 872 | 1066 | |
| 1067 | + slots = mcasp_get_tdm_slots(mcasp, stream); |
| 1068 | + |
| 873 | 1069 | /* In DIT mode we only allow maximum of one serializers for now */ |
| 874 | 1070 | if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE) |
| 875 | 1071 | max_active_serializers = 1; |
| @@ -997,7 +1193,7 @@ static int mcasp_i2s_hw_param(struct davinci_mcasp *mcasp, int stream, · 121 unmodified lines |
| 997 | 1193 | u32 mask = 0; |
| 998 | 1194 | u32 busel = 0; |
| 999 | 1195 | |
| 1000 | | − total_slots = mcasp->tdm_slots; |
| 1196 | + total_slots = mcasp_get_tdm_slots(mcasp, stream); |
| 1001 | 1197 | |
| 1002 | 1198 | /* |
| 1003 | 1199 | * If more than one serializer is needed, then use them with |
| @@ -1028,7 +1224,10 @@ static int mcasp_i2s_hw_param(struct davinci_mcasp *mcasp, int stream, · 24 unmodified lines |
| 1028 | 1224 | mask |= (1 << i); |
| 1029 | 1225 | } |
| 1030 | 1226 | |
| 1031 | | − mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, TX_ASYNC); |
| 1227 | + if (mcasp->async_mode) |
| 1228 | + mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, TX_ASYNC); |
| 1229 | + else |
| 1230 | + mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, TX_ASYNC); |
| 1032 | 1231 | |
| 1033 | 1232 | if (!mcasp->dat_port) |
| 1034 | 1233 | busel = TXSEL; |
| @@ -1127,16 +1326,33 @@ static int mcasp_dit_hw_param(struct davinci_mcasp *mcasp, · 92 unmodified lines |
| 1127 | 1326 | |
| 1128 | 1327 | static int davinci_mcasp_calc_clk_div(struct davinci_mcasp *mcasp, |
| 1129 | 1328 | unsigned int sysclk_freq, |
| 1130 | | − unsigned int bclk_freq, bool set) |
| 1329 | + unsigned int bclk_freq, |
| 1330 | + int stream, |
| 1331 | + bool set) |
| 1131 | 1332 | { |
| 1132 | | − u32 reg = mcasp_get_reg(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG); |
| 1133 | 1333 | int div = sysclk_freq / bclk_freq; |
| 1134 | 1334 | int rem = sysclk_freq % bclk_freq; |
| 1135 | 1335 | int error_ppm; |
| 1136 | 1336 | int aux_div = 1; |
| 1337 | + int bclk_div_id, auxclk_div_id; |
| 1338 | + bool auxclk_enabled; |
| 1339 | + |
| 1340 | + if (mcasp->async_mode && stream == SNDRV_PCM_STREAM_CAPTURE) { |
| 1341 | + auxclk_enabled = mcasp_get_reg(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG) & AHCLKRE; |
| 1342 | + bclk_div_id = MCASP_CLKDIV_BCLK_RXONLY; |
| 1343 | + auxclk_div_id = MCASP_CLKDIV_AUXCLK_RXONLY; |
| 1344 | + } else if (mcasp->async_mode && stream == SNDRV_PCM_STREAM_PLAYBACK) { |
| 1345 | + auxclk_enabled = mcasp_get_reg(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG) & AHCLKXE; |
| 1346 | + bclk_div_id = MCASP_CLKDIV_BCLK_TXONLY; |
| 1347 | + auxclk_div_id = MCASP_CLKDIV_AUXCLK_TXONLY; |
| 1348 | + } else { |
| 1349 | + auxclk_enabled = mcasp_get_reg(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG) & AHCLKXE; |
| 1350 | + bclk_div_id = MCASP_CLKDIV_BCLK; |
| 1351 | + auxclk_div_id = MCASP_CLKDIV_AUXCLK; |
| 1352 | + } |
| 1137 | 1353 | |
| 1138 | 1354 | if (div > (ACLKXDIV_MASK + 1)) { |
| 1139 | | − if (reg & AHCLKXE) { |
| 1355 | + if (auxclk_enabled) { |
| 1140 | 1356 | aux_div = div / (ACLKXDIV_MASK + 1); |
| 1141 | 1357 | if (div % (ACLKXDIV_MASK + 1)) |
| 1142 | 1358 | aux_div++; |
| @@ -1166,10 +1382,10 @@ static int davinci_mcasp_calc_clk_div(struct davinci_mcasp *mcasp, · 23 unmodified lines |
| 1166 | 1382 | dev_info(mcasp->dev, "Sample-rate is off by %d PPM\n", |
| 1167 | 1383 | error_ppm); |
| 1168 | 1384 | |
| 1169 | | − __davinci_mcasp_set_clkdiv(mcasp, MCASP_CLKDIV_BCLK, div, 0); |
| 1170 | | − if (reg & AHCLKXE) |
| 1171 | | − __davinci_mcasp_set_clkdiv(mcasp, MCASP_CLKDIV_AUXCLK, |
| 1172 | | − aux_div, 0); |
| 1385 | + __davinci_mcasp_set_clkdiv(mcasp, bclk_div_id, div, false); |
| 1386 | + if (auxclk_enabled) |
| 1387 | + __davinci_mcasp_set_clkdiv(mcasp, auxclk_div_id, |
| 1388 | + aux_div, false); |
| 1173 | 1389 | } |
| 1174 | 1390 | |
| 1175 | 1391 | return error_ppm; |
| @@ -1220,6 +1436,7 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, · 44 unmodified lines |
| 1220 | 1436 | int channels = params_channels(params); |
| 1221 | 1437 | int period_size = params_period_size(params); |
| 1222 | 1438 | int ret; |
| 1439 | + unsigned int sysclk_freq = mcasp_get_sysclk_freq(mcasp, substream->stream); |
| 1223 | 1440 | |
| 1224 | 1441 | switch (params_format(params)) { |
| 1225 | 1442 | case SNDRV_PCM_FORMAT_U8: |
| @@ -1260,22 +1477,26 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, · 34 unmodified lines |
| 1260 | 1477 | * If mcasp is BCLK master, and a BCLK divider was not provided by |
| 1261 | 1478 | * the machine driver, we need to calculate the ratio. |
| 1262 | 1479 | */ |
| 1263 | | − if (mcasp->bclk_master && mcasp->bclk_div == 0 && mcasp->sysclk_freq) { |
| 1264 | | − int slots = mcasp->tdm_slots; |
| 1480 | + if (mcasp->bclk_master && mcasp_get_bclk_div(mcasp, substream->stream) == 0 && |
| 1481 | + sysclk_freq) { |
| 1482 | + int slots, slot_width; |
| 1265 | 1483 | int rate = params_rate(params); |
| 1266 | 1484 | int sbits = params_width(params); |
| 1267 | 1485 | unsigned int bclk_target; |
| 1268 | 1486 | |
| 1269 | | − if (mcasp->slot_width) |
| 1270 | | − sbits = mcasp->slot_width; |
| 1487 | + slots = mcasp_get_tdm_slots(mcasp, substream->stream); |
| 1488 | + |
| 1489 | + slot_width = mcasp_get_slot_width(mcasp, substream->stream); |
| 1490 | + if (slot_width) |
| 1491 | + sbits = slot_width; |
| 1271 | 1492 | |
| 1272 | 1493 | if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE) |
| 1273 | 1494 | bclk_target = rate * sbits * slots; |
| 1274 | 1495 | else |
| 1275 | 1496 | bclk_target = rate * 128; |
| 1276 | 1497 | |
| 1277 | | − davinci_mcasp_calc_clk_div(mcasp, mcasp->sysclk_freq, |
| 1278 | | − bclk_target, true); |
| 1498 | + davinci_mcasp_calc_clk_div(mcasp, sysclk_freq, |
| 1499 | + bclk_target, substream->stream, true); |
| 1279 | 1500 | } |
| 1280 | 1501 | |
| 1281 | 1502 | ret = mcasp_common_hw_param(mcasp, substream->stream, |
| @@ -1292,9 +1513,10 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, · 10 unmodified lines |
| 1292 | 1513 | if (ret) |
| 1293 | 1514 | return ret; |
| 1294 | 1515 | |
| 1295 | | − davinci_config_channel_size(mcasp, word_length); |
| 1516 | + davinci_config_channel_size(mcasp, word_length, substream->stream); |
| 1296 | 1517 | |
| 1297 | | − if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE) { |
| 1518 | + /* Channel constraints are disabled for async mode */ |
| 1519 | + if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE && !mcasp->async_mode) { |
| 1298 | 1520 | mcasp->channels = channels; |
| 1299 | 1521 | if (!mcasp->max_format_width) |
| 1300 | 1522 | mcasp->max_format_width = word_length; |
| @@ -1338,7 +1560,7 @@ static int davinci_mcasp_hw_rule_slot_width(struct snd_pcm_hw_params *params, · 37 unmodified lines |
| 1338 | 1560 | snd_pcm_format_t i; |
| 1339 | 1561 | |
| 1340 | 1562 | snd_mask_none(&nfmt); |
| 1341 | | − slot_width = rd->mcasp->slot_width; |
| 1563 | + slot_width = mcasp_get_slot_width(rd->mcasp, rd->stream); |
| 1342 | 1564 | |
| 1343 | 1565 | pcm_for_each_format(i) { |
| 1344 | 1566 | if (snd_mask_test_format(fmt, i)) { |
| @@ -1388,12 +1610,15 @@ static int davinci_mcasp_hw_rule_rate(struct snd_pcm_hw_params *params, · 43 unmodified lines |
| 1388 | 1610 | struct snd_interval *ri = |
| 1389 | 1611 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); |
| 1390 | 1612 | int sbits = params_width(params); |
| 1391 | | − int slots = rd->mcasp->tdm_slots; |
| 1613 | + int slots, slot_width; |
| 1392 | 1614 | struct snd_interval range; |
| 1393 | 1615 | int i; |
| 1394 | 1616 | |
| 1395 | | − if (rd->mcasp->slot_width) |
| 1396 | | − sbits = rd->mcasp->slot_width; |
| 1617 | + slots = mcasp_get_tdm_slots(rd->mcasp, rd->stream); |
| 1618 | + |
| 1619 | + slot_width = mcasp_get_slot_width(rd->mcasp, rd->stream); |
| 1620 | + if (slot_width) |
| 1621 | + sbits = slot_width; |
| 1397 | 1622 | |
| 1398 | 1623 | snd_interval_any(&range); |
| 1399 | 1624 | range.empty = 1; |
| @@ -1403,16 +1628,17 @@ static int davinci_mcasp_hw_rule_rate(struct snd_pcm_hw_params *params, · 3 unmodified lines |
| 1403 | 1628 | uint bclk_freq = sbits * slots * |
| 1404 | 1629 | davinci_mcasp_dai_rates[i]; |
| 1405 | 1630 | unsigned int sysclk_freq; |
| 1631 | + unsigned int ratio; |
| 1406 | 1632 | int ppm; |
| 1407 | 1633 | |
| 1408 | | − if (rd->mcasp->auxclk_fs_ratio) |
| 1409 | | − sysclk_freq = davinci_mcasp_dai_rates[i] * |
| 1410 | | − rd->mcasp->auxclk_fs_ratio; |
| 1634 | + ratio = mcasp_get_auxclk_fs_ratio(rd->mcasp, rd->stream); |
| 1635 | + if (ratio) |
| 1636 | + sysclk_freq = davinci_mcasp_dai_rates[i] * ratio; |
| 1411 | 1637 | else |
| 1412 | | − sysclk_freq = rd->mcasp->sysclk_freq; |
| 1638 | + sysclk_freq = mcasp_get_sysclk_freq(rd->mcasp, rd->stream); |
| 1413 | 1639 | |
| 1414 | 1640 | ppm = davinci_mcasp_calc_clk_div(rd->mcasp, sysclk_freq, |
| 1415 | | − bclk_freq, false); |
| 1641 | + bclk_freq, rd->stream, false); |
| 1416 | 1642 | if (abs(ppm) < DAVINCI_MAX_RATE_ERROR_PPM) { |
| 1417 | 1643 | if (range.empty) { |
| 1418 | 1644 | range.min = davinci_mcasp_dai_rates[i]; |
| @@ -1438,30 +1664,34 @@ static int davinci_mcasp_hw_rule_format(struct snd_pcm_hw_params *params, · 19 unmodified lines |
| 1438 | 1664 | struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); |
| 1439 | 1665 | struct snd_mask nfmt; |
| 1440 | 1666 | int rate = params_rate(params); |
| 1441 | | − int slots = rd->mcasp->tdm_slots; |
| 1667 | + int slots; |
| 1442 | 1668 | int count = 0; |
| 1443 | 1669 | snd_pcm_format_t i; |
| 1444 | 1670 | |
| 1671 | + slots = mcasp_get_tdm_slots(rd->mcasp, rd->stream); |
| 1672 | + |
| 1445 | 1673 | snd_mask_none(&nfmt); |
| 1446 | 1674 | |
| 1447 | 1675 | pcm_for_each_format(i) { |
| 1448 | 1676 | if (snd_mask_test_format(fmt, i)) { |
| 1449 | 1677 | uint sbits = snd_pcm_format_width(i); |
| 1450 | 1678 | unsigned int sysclk_freq; |
| 1451 | | − int ppm; |
| 1679 | + unsigned int ratio; |
| 1680 | + int ppm, slot_width; |
| 1452 | 1681 | |
| 1453 | | − if (rd->mcasp->auxclk_fs_ratio) |
| 1454 | | − sysclk_freq = rate * |
| 1455 | | − rd->mcasp->auxclk_fs_ratio; |
| 1682 | + ratio = mcasp_get_auxclk_fs_ratio(rd->mcasp, rd->stream); |
| 1683 | + if (ratio) |
| 1684 | + sysclk_freq = rate * ratio; |
| 1456 | 1685 | else |
| 1457 | | − sysclk_freq = rd->mcasp->sysclk_freq; |
| 1686 | + sysclk_freq = mcasp_get_sysclk_freq(rd->mcasp, rd->stream); |
| 1458 | 1687 | |
| 1459 | | − if (rd->mcasp->slot_width) |
| 1460 | | − sbits = rd->mcasp->slot_width; |
| 1688 | + slot_width = mcasp_get_slot_width(rd->mcasp, rd->stream); |
| 1689 | + if (slot_width) |
| 1690 | + sbits = slot_width; |
| 1461 | 1691 | |
| 1462 | 1692 | ppm = davinci_mcasp_calc_clk_div(rd->mcasp, sysclk_freq, |
| 1463 | 1693 | sbits * slots * rate, |
| 1464 | | − false); |
| 1694 | + rd->stream, false); |
| 1465 | 1695 | if (abs(ppm) < DAVINCI_MAX_RATE_ERROR_PPM) { |
| 1466 | 1696 | snd_mask_set_format(&nfmt, i); |
| 1467 | 1697 | count++; |
| @@ -1498,7 +1728,7 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream, · 30 unmodified lines |
| 1498 | 1728 | &mcasp->ruledata[substream->stream]; |
| 1499 | 1729 | u32 max_channels = 0; |
| 1500 | 1730 | int i, dir, ret; |
| 1501 | | − int tdm_slots = mcasp->tdm_slots; |
| 1731 | + int tdm_slots; |
| 1502 | 1732 | u8 *numevt; |
| 1503 | 1733 | |
| 1504 | 1734 | /* Do not allow more then one stream per direction */ |
| @@ -1507,6 +1737,8 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream, · 2 unmodified lines |
| 1507 | 1737 | |
| 1508 | 1738 | mcasp->substreams[substream->stream] = substream; |
| 1509 | 1739 | |
| 1740 | + tdm_slots = mcasp_get_tdm_slots(mcasp, substream->stream); |
| 1741 | + |
| 1510 | 1742 | if (mcasp->tdm_mask[substream->stream]) |
| 1511 | 1743 | tdm_slots = hweight32(mcasp->tdm_mask[substream->stream]); |
| 1512 | 1744 | |
| @@ -1528,6 +1760,7 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream, · 15 unmodified lines |
| 1528 | 1760 | } |
| 1529 | 1761 | ruledata->serializers = max_channels; |
| 1530 | 1762 | ruledata->mcasp = mcasp; |
| 1763 | + ruledata->stream = substream->stream; |
| 1531 | 1764 | max_channels *= tdm_slots; |
| 1532 | 1765 | /* |
| 1533 | 1766 | * If the already active stream has less channels than the calculated |
| @@ -1535,9 +1768,13 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream, · 1 unmodified line |
| 1535 | 1768 | * is in use we need to use that as a constraint for the second stream. |
| 1536 | 1769 | * Otherwise (first stream or less allowed channels or more than one |
| 1537 | 1770 | * serializer in use) we use the calculated constraint. |
| 1771 | + * |
| 1772 | + * However, in async mode, TX and RX have independent clocks and can |
| 1773 | + * use different configurations, so don't apply the constraint. |
| 1538 | 1774 | */ |
| 1539 | 1775 | if (mcasp->channels && mcasp->channels < max_channels && |
| 1540 | | − ruledata->serializers == 1) |
| 1776 | + ruledata->serializers == 1 && |
| 1777 | + !mcasp->async_mode) |
| 1541 | 1778 | max_channels = mcasp->channels; |
| 1542 | 1779 | /* |
| 1543 | 1780 | * But we can always allow channels upto the amount of |
| @@ -1554,10 +1791,10 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream, · 10 unmodified lines |
| 1554 | 1791 | 0, SNDRV_PCM_HW_PARAM_CHANNELS, |
| 1555 | 1792 | &mcasp->chconstr[substream->stream]); |
| 1556 | 1793 | |
| 1557 | | − if (mcasp->max_format_width) { |
| 1794 | + if (mcasp->max_format_width && !mcasp->async_mode) { |
| 1558 | 1795 | /* |
| 1559 | 1796 | * Only allow formats which require same amount of bits on the |
| 1560 | | − * bus as the currently running stream |
| 1797 | + * bus as the currently running stream to ensure sync mode |
| 1561 | 1798 | */ |
| 1562 | 1799 | ret = snd_pcm_hw_rule_add(substream->runtime, 0, |
| 1563 | 1800 | SNDRV_PCM_HW_PARAM_FORMAT, |
| @@ -1566,8 +1803,7 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream, · 2 unmodified lines |
| 1566 | 1803 | SNDRV_PCM_HW_PARAM_FORMAT, -1); |
| 1567 | 1804 | if (ret) |
| 1568 | 1805 | return ret; |
| 1569 | | − } |
| 1570 | | − else if (mcasp->slot_width) { |
| 1806 | + } else if (mcasp_get_slot_width(mcasp, substream->stream)) { |
| 1571 | 1807 | /* Only allow formats require <= slot_width bits on the bus */ |
| 1572 | 1808 | ret = snd_pcm_hw_rule_add(substream->runtime, 0, |
| 1573 | 1809 | SNDRV_PCM_HW_PARAM_FORMAT, |
| @@ -1582,7 +1818,8 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream, · 8 unmodified lines |
| 1582 | 1818 | * If we rely on implicit BCLK divider setting we should |
| 1583 | 1819 | * set constraints based on what we can provide. |
| 1584 | 1820 | */ |
| 1585 | | − if (mcasp->bclk_master && mcasp->bclk_div == 0 && mcasp->sysclk_freq) { |
| 1821 | + if (mcasp->bclk_master && mcasp_get_bclk_div(mcasp, substream->stream) == 0 && |
| 1822 | + mcasp_get_sysclk_freq(mcasp, substream->stream)) { |
| 1586 | 1823 | ret = snd_pcm_hw_rule_add(substream->runtime, 0, |
| 1587 | 1824 | SNDRV_PCM_HW_PARAM_RATE, |
| 1588 | 1825 | davinci_mcasp_hw_rule_rate, |
| @@ -1759,8 +1996,6 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = { · 170 unmodified lines |
| 1759 | 1996 | .formats = DAVINCI_MCASP_PCM_FMTS, |
| 1760 | 1997 | }, |
| 1761 | 1998 | .ops = &davinci_mcasp_dai_ops, |
| 1762 | | − |
| 1763 | | − .symmetric_rate = 1, |
| 1764 | 1999 | }, |
| 1765 | 2000 | { |
| 1766 | 2001 | .name = "davinci-mcasp.1", |
| @@ -1918,18 +2153,33 @@ static int davinci_mcasp_get_config(struct davinci_mcasp *mcasp, · 151 unmodified lines |
| 1918 | 2153 | goto out; |
| 1919 | 2154 | } |
| 1920 | 2155 | |
| 2156 | + /* Parse TX-specific TDM slot and use it as default for RX */ |
| 1921 | 2157 | if (of_property_read_u32(np, "tdm-slots", &val) == 0) { |
| 1922 | 2158 | if (val < 2 || val > 32) { |
| 1923 | | − dev_err(&pdev->dev, "tdm-slots must be in rage [2-32]\n"); |
| 2159 | + dev_err(&pdev->dev, "tdm-slots must be in range [2-32]\n"); |
| 1924 | 2160 | return -EINVAL; |
| 1925 | 2161 | } |
| 1926 | 2162 | |
| 1927 | | − pdata->tdm_slots = val; |
| 2163 | + pdata->tdm_slots_tx = val; |
| 2164 | + pdata->tdm_slots_rx = val; |
| 1928 | 2165 | } else if (pdata->op_mode == DAVINCI_MCASP_IIS_MODE) { |
| 1929 | 2166 | mcasp->missing_audio_param = true; |
| 1930 | 2167 | goto out; |
| 1931 | 2168 | } |
| 1932 | 2169 | |
| 2170 | + /* Parse RX-specific TDM slot count if provided */ |
| 2171 | + if (of_property_read_u32(np, "tdm-slots-rx", &val) == 0) { |
| 2172 | + if (val < 2 || val > 32) { |
| 2173 | + dev_err(&pdev->dev, "tdm-slots-rx must be in range [2-32]\n"); |
| 2174 | + return -EINVAL; |
| 2175 | + } |
| 2176 | + |
| 2177 | + pdata->tdm_slots_rx = val; |
| 2178 | + } |
| 2179 | + |
| 2180 | + if (pdata->op_mode != DAVINCI_MCASP_DIT_MODE) |
| 2181 | + mcasp->async_mode = of_property_read_bool(np, "ti,async-mode"); |
| 2182 | + |
| 1933 | 2183 | of_serial_dir32 = of_get_property(np, "serial-dir", &val); |
| 1934 | 2184 | val /= sizeof(u32); |
| 1935 | 2185 | if (of_serial_dir32) { |
| @@ -1955,8 +2205,15 @@ static int davinci_mcasp_get_config(struct davinci_mcasp *mcasp, · 19 unmodified lines |
| 1955 | 2205 | if (of_property_read_u32(np, "rx-num-evt", &val) == 0) |
| 1956 | 2206 | pdata->rxnumevt = val; |
| 1957 | 2207 | |
| 1958 | | − if (of_property_read_u32(np, "auxclk-fs-ratio", &val) == 0) |
| 1959 | | − mcasp->auxclk_fs_ratio = val; |
| 2208 | + /* Parse TX-specific auxclk/fs ratio and use it as default for RX */ |
| 2209 | + if (of_property_read_u32(np, "auxclk-fs-ratio", &val) == 0) { |
| 2210 | + mcasp->auxclk_fs_ratio_tx = val; |
| 2211 | + mcasp->auxclk_fs_ratio_rx = val; |
| 2212 | + } |
| 2213 | + |
| 2214 | + /* Parse RX-specific auxclk/fs ratio if provided */ |
| 2215 | + if (of_property_read_u32(np, "auxclk-fs-ratio-rx", &val) == 0) |
| 2216 | + mcasp->auxclk_fs_ratio_rx = val; |
| 1960 | 2217 | |
| 1961 | 2218 | if (of_property_read_u32(np, "dismod", &val) == 0) { |
| 1962 | 2219 | if (val == 0 || val == 2 || val == 3) { |
| @@ -1985,19 +2242,51 @@ out: · 22 unmodified lines |
| 1985 | 2242 | mcasp->op_mode = pdata->op_mode; |
| 1986 | 2243 | /* sanity check for tdm slots parameter */ |
| 1987 | 2244 | if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE) { |
| 1988 | | − if (pdata->tdm_slots < 2) { |
| 1989 | | − dev_warn(&pdev->dev, "invalid tdm slots: %d\n", |
| 1990 | | − pdata->tdm_slots); |
| 1991 | | − mcasp->tdm_slots = 2; |
| 1992 | | − } else if (pdata->tdm_slots > 32) { |
| 1993 | | − dev_warn(&pdev->dev, "invalid tdm slots: %d\n", |
| 1994 | | − pdata->tdm_slots); |
| 1995 | | − mcasp->tdm_slots = 32; |
| 2245 | + if (pdata->tdm_slots_tx < 2) { |
| 2246 | + dev_warn(&pdev->dev, "invalid tdm tx slots: %d\n", |
| 2247 | + pdata->tdm_slots_tx); |
| 2248 | + mcasp->tdm_slots_tx = 2; |
| 2249 | + } else if (pdata->tdm_slots_tx > 32) { |
| 2250 | + dev_warn(&pdev->dev, "invalid tdm tx slots: %d\n", |
| 2251 | + pdata->tdm_slots_tx); |
| 2252 | + mcasp->tdm_slots_tx = 32; |
| 2253 | + } else { |
| 2254 | + mcasp->tdm_slots_tx = pdata->tdm_slots_tx; |
| 2255 | + } |
| 2256 | + |
| 2257 | + if (pdata->tdm_slots_rx < 2) { |
| 2258 | + dev_warn(&pdev->dev, "invalid tdm rx slots: %d\n", |
| 2259 | + pdata->tdm_slots_rx); |
| 2260 | + mcasp->tdm_slots_rx = 2; |
| 2261 | + } else if (pdata->tdm_slots_rx > 32) { |
| 2262 | + dev_warn(&pdev->dev, "invalid tdm rx slots: %d\n", |
| 2263 | + pdata->tdm_slots_rx); |
| 2264 | + mcasp->tdm_slots_rx = 32; |
| 1996 | 2265 | } else { |
| 1997 | | − mcasp->tdm_slots = pdata->tdm_slots; |
| 2266 | + mcasp->tdm_slots_rx = pdata->tdm_slots_rx; |
| 1998 | 2267 | } |
| 1999 | 2268 | } else { |
| 2000 | | − mcasp->tdm_slots = 32; |
| 2269 | + mcasp->tdm_slots_tx = 32; |
| 2270 | + mcasp->tdm_slots_rx = 32; |
| 2271 | + } |
| 2272 | + |
| 2273 | + /* Different TX/RX slot counts require async mode */ |
| 2274 | + if (pdata->op_mode != DAVINCI_MCASP_DIT_MODE && |
| 2275 | + mcasp->tdm_slots_tx != mcasp->tdm_slots_rx && !mcasp->async_mode) { |
| 2276 | + dev_err(&pdev->dev, |
| 2277 | + "Different TX (%d) and RX (%d) TDM slots require ti,async-mode\n", |
| 2278 | + mcasp->tdm_slots_tx, mcasp->tdm_slots_rx); |
| 2279 | + return -EINVAL; |
| 2280 | + } |
| 2281 | + |
| 2282 | + /* Different TX/RX auxclk-fs-ratio require async mode */ |
| 2283 | + if (pdata->op_mode != DAVINCI_MCASP_DIT_MODE && |
| 2284 | + mcasp->auxclk_fs_ratio_tx && mcasp->auxclk_fs_ratio_rx && |
| 2285 | + mcasp->auxclk_fs_ratio_tx != mcasp->auxclk_fs_ratio_rx && !mcasp->async_mode) { |
| 2286 | + dev_err(&pdev->dev, |
| 2287 | + "Different TX (%d) and RX (%d) auxclk-fs-ratio require ti,async-mode\n", |
| 2288 | + mcasp->auxclk_fs_ratio_tx, mcasp->auxclk_fs_ratio_rx); |
| 2289 | + return -EINVAL; |
| 2001 | 2290 | } |
| 2002 | 2291 | |
| 2003 | 2292 | mcasp->num_serializer = pdata->num_serializer; |