History

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.

Sen Wang committed 9 months ago

Commit 9db32701 parent 016efca3 files · +401 −101Browse files

Unified · Split

3 files
  1. include/linux/platform_data/davinci_asp.h +2 −1
  2. sound/soc/ti/davinci-mcasp.c +389 −100
  3. sound/soc/ti/davinci-mcasp.h +10 −0
include/linux/platform_data/davinci_asp.h+2−1
@@ -59,7 +59,8 @@ struct davinci_mcasp_pdata { · 58 unmodified lines
59 bool i2s_accurate_sck;59 bool i2s_accurate_sck;
60 60
61 /* McASP specific fields */61 /* McASP specific fields */
62 int tdm_slots;62 int tdm_slots_tx;
63 int tdm_slots_rx;
63 u8 op_mode;64 u8 op_mode;
64 u8 dismod;65 u8 dismod;
65 u8 num_serializer;66 u8 num_serializer;
sound/soc/ti/davinci-mcasp.c+389−100
@@ -71,6 +71,7 @@ struct davinci_mcasp_context { · 70 unmodified lines
71struct davinci_mcasp_ruledata {71struct davinci_mcasp_ruledata {
72 struct davinci_mcasp *mcasp;72 struct davinci_mcasp *mcasp;
73 int serializers;73 int serializers;
74 int stream;
74};75};
75 76
76struct davinci_mcasp {77struct davinci_mcasp {
@@ -88,21 +89,27 @@ struct davinci_mcasp { · 11 unmodified lines
88 bool missing_audio_param;89 bool missing_audio_param;
89 90
90 /* McASP specific data */91 /* McASP specific data */
91 int tdm_slots;92 int tdm_slots_tx;
93 int tdm_slots_rx;
92 u32 tdm_mask[2];94 u32 tdm_mask[2];
93 int slot_width;95 int slot_width_tx;
96 int slot_width_rx;
94 u8 op_mode;97 u8 op_mode;
95 u8 dismod;98 u8 dismod;
96 u8 num_serializer;99 u8 num_serializer;
97 u8 *serial_dir;100 u8 *serial_dir;
98 u8 version;101 u8 version;
99 u8 bclk_div;102 u8 bclk_div_tx;
103 u8 bclk_div_rx;
100 int streams;104 int streams;
101 u32 irq_request[2];105 u32 irq_request[2];
102 106
103 int sysclk_freq;107 unsigned int sysclk_freq_tx;
108 unsigned int sysclk_freq_rx;
104 bool bclk_master;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 unsigned long pdir; /* Pin direction bitfield */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
214static 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
207static inline void mcasp_set_axr_pdir(struct davinci_mcasp *mcasp, bool enable)235static inline void mcasp_set_axr_pdir(struct davinci_mcasp *mcasp, bool enable)
208{236{
209 u32 bit;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
247static 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
253static 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
259static 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
265static 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
271static 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
219static void mcasp_start_rx(struct davinci_mcasp *mcasp)277static void mcasp_start_rx(struct davinci_mcasp *mcasp)
220{278{
221 if (mcasp->rxnumevt) { /* enable FIFO */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 * When ASYNC == 0 the transmit and receive sections operate290 * When ASYNC == 0 the transmit and receive sections operate
233 * synchronously from the transmit clock and frame sync. We need to make291 * 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 if (mcasp_is_frame_producer(mcasp) && mcasp_is_synchronous(mcasp)) {295 if (mcasp_is_frame_producer(mcasp) && mcasp_is_synchronous(mcasp)) {
237 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST);296 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST);
238 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST);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 /* Activate serializer(s) */304 /* Activate serializer(s) */
243 mcasp_set_reg(mcasp, DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF);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 /* Start clocks */330 /* Start clocks */
269 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST);331 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST);
270 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST);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 /* Activate serializer(s) */338 /* Activate serializer(s) */
274 mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF);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 * In synchronous mode stop the TX clocks if no other stream is377 * In synchronous mode stop the TX clocks if no other stream is
313 * running378 * 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 mcasp_set_clk_pdir(mcasp, false);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 if (mcasp_is_frame_producer(mcasp) && mcasp_is_synchronous(mcasp) && !mcasp->streams)390 if (mcasp_is_frame_producer(mcasp) && mcasp_is_synchronous(mcasp) && !mcasp->streams)
318 mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, 0);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 * In synchronous mode keep TX clocks running if the capture stream is412 * In synchronous mode keep TX clocks running if the capture stream is
340 * still running.413 * still running.
414 * Otherwise in async mode only stop TX clocks
341 */415 */
342 if (mcasp_is_frame_producer(mcasp) && mcasp_is_synchronous(mcasp) && mcasp->streams)416 if (mcasp_is_frame_producer(mcasp) && mcasp_is_synchronous(mcasp) && mcasp->streams)
343 val = TXHCLKRST | TXCLKRST | TXFSRST;417 val = TXHCLKRST | TXCLKRST | TXFSRST;
344 if (!mcasp->streams)418 if (mcasp_is_synchronous(mcasp) && !mcasp->streams)
345 mcasp_set_clk_pdir(mcasp, false);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 mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, val);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 AHCLKRDIV(div - 1), AHCLKRDIV_MASK);702 AHCLKRDIV(div - 1), AHCLKRDIV_MASK);
627 break;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 case MCASP_CLKDIV_BCLK: /* BCLK divider */715 case MCASP_CLKDIV_BCLK: /* BCLK divider */
630 mcasp_mod_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG,716 mcasp_mod_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG,
631 ACLKXDIV(div - 1), ACLKXDIV_MASK);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 mcasp_mod_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG,734 mcasp_mod_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG,
633 ACLKRDIV(div - 1), ACLKRDIV_MASK);735 ACLKRDIV(div - 1), ACLKRDIV_MASK);
634 if (explicit)736 if (explicit)
635 mcasp->bclk_div = div;737 mcasp->bclk_div_rx = div;
636 break;738 break;
637 739
638 case MCASP_CLKDIV_BCLK_FS_RATIO: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 * tdm_slot width by dividing the ratio by the748 * tdm_slot width by dividing the ratio by the
647 * number of configured tdm slots.749 * number of configured tdm slots.
648 */750 */
649 mcasp->slot_width = div / mcasp->tdm_slots;751 mcasp->slot_width_tx = div / mcasp->tdm_slots_tx;
650 if (div % mcasp->tdm_slots)752 if (div % mcasp->tdm_slots_tx)
651 dev_warn(mcasp->dev,753 dev_warn(mcasp->dev,
652 "%s(): BCLK/LRCLK %d is not divisible by %d tdm slots",754 "%s(): BCLK/LRCLK %d is not divisible by %d tx tdm slots",
653 __func__, div, mcasp->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 break;778 break;
655 779
656 default:780 default:
@@ -684,6 +808,20 @@ static int davinci_mcasp_set_sysclk(struct snd_soc_dai *dai, int clk_id, · 27 unmodified lines
684 mcasp_clr_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG,808 mcasp_clr_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG,
685 AHCLKRE);809 AHCLKRE);
686 clear_bit(PIN_BIT_AHCLKX, &mcasp->pdir);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 break;825 break;
688 case MCASP_CLK_HCLK_AUXCLK:826 case MCASP_CLK_HCLK_AUXCLK:
689 mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG,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 mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG,829 mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG,
692 AHCLKRE);830 AHCLKRE);
693 set_bit(PIN_BIT_AHCLKX, &mcasp->pdir);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 break;846 break;
695 default:847 default:
696 dev_err(mcasp->dev, "Invalid clk id: %d\n", clk_id);848 dev_err(mcasp->dev, "Invalid clk id: %d\n", clk_id);
697 goto out;849 goto out;
698 }850 }
699 } else {851 } else {
700 /* Select AUXCLK as HCLK */852 /* McASP is clock master, select AUXCLK as HCLK */
701 mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE);853 switch (clk_id) {
702 mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, AHCLKRE);854 case MCASP_CLK_HCLK_AUXCLK_TXONLY:
703 set_bit(PIN_BIT_AHCLKX, &mcasp->pdir);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 * When AHCLK X/R is selected to be output it means that the HCLK is879 * When AHCLK X/R is selected to be output it means that the HCLK is
707 * the same clock - coming via AUXCLK.880 * the same clock - coming via AUXCLK.
708 */881 */
709 mcasp->sysclk_freq = freq;
710out:882out:
711 pm_runtime_put(mcasp->dev);883 pm_runtime_put(mcasp->dev);
712 return 0;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 struct snd_pcm_hw_constraint_list *cl = &mcasp->chconstr[stream];891 struct snd_pcm_hw_constraint_list *cl = &mcasp->chconstr[stream];
720 unsigned int *list = (unsigned int *) cl->list;892 unsigned int *list = (unsigned int *) cl->list;
721 int slots = mcasp->tdm_slots;893 int slots;
722 int i, count = 0;894 int i, count = 0;
723 895
896 slots = mcasp_get_tdm_slots(mcasp, stream);
897
724 if (mcasp->tdm_mask[stream])898 if (mcasp->tdm_mask[stream])
725 slots = hweight32(mcasp->tdm_mask[stream]);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 return -EINVAL;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 mcasp->tdm_mask[SNDRV_PCM_STREAM_PLAYBACK] = tx_mask;978 mcasp->tdm_mask[SNDRV_PCM_STREAM_PLAYBACK] = tx_mask;
790 mcasp->tdm_mask[SNDRV_PCM_STREAM_CAPTURE] = rx_mask;979 mcasp->tdm_mask[SNDRV_PCM_STREAM_CAPTURE] = rx_mask;
791 mcasp->slot_width = slot_width;
792 980
793 return davinci_mcasp_set_ch_constraints(mcasp);981 return davinci_mcasp_set_ch_constraints(mcasp);
794}982}
795 983
796static int davinci_config_channel_size(struct davinci_mcasp *mcasp,984static int davinci_config_channel_size(struct davinci_mcasp *mcasp,
797 int sample_width)985 int sample_width, int stream)
798{986{
799 u32 fmt;987 u32 fmt;
800 u32 tx_rotate, rx_rotate, slot_width;988 u32 tx_rotate, rx_rotate, slot_width;
801 u32 mask = (1ULL << sample_width) - 1;989 u32 mask = (1ULL << sample_width) - 1;
802 990
803 if (mcasp->slot_width)991 slot_width = mcasp_get_slot_width(mcasp, stream);
804 slot_width = mcasp->slot_width;992 if (!slot_width) {
805 else if (mcasp->max_format_width)993 if (mcasp->max_format_width)
806 slot_width = mcasp->max_format_width;994 slot_width = mcasp->max_format_width;
807 else995 else
808 slot_width = sample_width;996 slot_width = sample_width;
997 }
809 /*998 /*
810 * TX rotation:999 * TX rotation:
811 * right aligned formats: rotate w/ slot_width1000 * 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 fmt = (slot_width >> 1) - 1;1017 fmt = (slot_width >> 1) - 1;
829 1018
830 if (mcasp->op_mode != DAVINCI_MCASP_DIT_MODE) {1019 if (mcasp->op_mode != DAVINCI_MCASP_DIT_MODE) {
831 mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, RXSSZ(fmt),1020 if (!mcasp->async_mode || stream == SNDRV_PCM_STREAM_PLAYBACK) {
832 RXSSZ(0x0F));1021 mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXSSZ(fmt),
833 mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXSSZ(fmt),1022 TXSSZ(0x0F));
834 TXSSZ(0x0F));1023 mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXROT(tx_rotate),
835 mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXROT(tx_rotate),1024 TXROT(7));
836 TXROT(7));1025 mcasp_set_reg(mcasp, DAVINCI_MCASP_TXMASK_REG, mask);
837 mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, RXROT(rx_rotate),1026 }
838 RXROT(7));1027 if (!mcasp->async_mode || stream == SNDRV_PCM_STREAM_CAPTURE) {
839 mcasp_set_reg(mcasp, DAVINCI_MCASP_RXMASK_REG, mask);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 } else {1034 } else {
841 /*1035 /*
1036 * DIT mode only use TX serializers
842 * according to the TRM it should be TXROT=0, this one works:1037 * according to the TRM it should be TXROT=0, this one works:
843 * 16 bit to 23-8 (TXROT=6, rotate 24 bits)1038 * 16 bit to 23-8 (TXROT=6, rotate 24 bits)
844 * 24 bit to 23-0 (TXROT=0, rotate 0 bits)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 TXROT(7));1046 TXROT(7));
852 mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXSSZ(15),1047 mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXSSZ(15),
853 TXSSZ(0x0F));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 return 0;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 int i;1059 int i;
866 u8 tx_ser = 0;1060 u8 tx_ser = 0;
867 u8 rx_ser = 0;1061 u8 rx_ser = 0;
868 u8 slots = mcasp->tdm_slots;1062 int slots;
869 u8 max_active_serializers, max_rx_serializers, max_tx_serializers;1063 u8 max_active_serializers, max_rx_serializers, max_tx_serializers;
870 int active_serializers, numevt;1064 int active_serializers, numevt;
871 u32 reg;1065 u32 reg;
872 1066
1067 slots = mcasp_get_tdm_slots(mcasp, stream);
1068
873 /* In DIT mode we only allow maximum of one serializers for now */1069 /* In DIT mode we only allow maximum of one serializers for now */
874 if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE)1070 if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE)
875 max_active_serializers = 1;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 u32 mask = 0;1193 u32 mask = 0;
998 u32 busel = 0;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 * If more than one serializer is needed, then use them with1199 * 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 mask |= (1 << i);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 if (!mcasp->dat_port)1232 if (!mcasp->dat_port)
1034 busel = TXSEL;1233 busel = TXSEL;
@@ -1127,16 +1326,33 @@ static int mcasp_dit_hw_param(struct davinci_mcasp *mcasp, · 92 unmodified lines
1127 1326
1128static int davinci_mcasp_calc_clk_div(struct davinci_mcasp *mcasp,1327static int davinci_mcasp_calc_clk_div(struct davinci_mcasp *mcasp,
1129 unsigned int sysclk_freq,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 int div = sysclk_freq / bclk_freq;1333 int div = sysclk_freq / bclk_freq;
1134 int rem = sysclk_freq % bclk_freq;1334 int rem = sysclk_freq % bclk_freq;
1135 int error_ppm;1335 int error_ppm;
1136 int aux_div = 1;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 if (div > (ACLKXDIV_MASK + 1)) {1354 if (div > (ACLKXDIV_MASK + 1)) {
1139 if (reg & AHCLKXE) {1355 if (auxclk_enabled) {
1140 aux_div = div / (ACLKXDIV_MASK + 1);1356 aux_div = div / (ACLKXDIV_MASK + 1);
1141 if (div % (ACLKXDIV_MASK + 1))1357 if (div % (ACLKXDIV_MASK + 1))
1142 aux_div++;1358 aux_div++;
@@ -1166,10 +1382,10 @@ static int davinci_mcasp_calc_clk_div(struct davinci_mcasp *mcasp, · 23 unmodified lines
1166 dev_info(mcasp->dev, "Sample-rate is off by %d PPM\n",1382 dev_info(mcasp->dev, "Sample-rate is off by %d PPM\n",
1167 error_ppm);1383 error_ppm);
1168 1384
1169 __davinci_mcasp_set_clkdiv(mcasp, MCASP_CLKDIV_BCLK, div, 0);1385 __davinci_mcasp_set_clkdiv(mcasp, bclk_div_id, div, false);
1170 if (reg & AHCLKXE)1386 if (auxclk_enabled)
1171 __davinci_mcasp_set_clkdiv(mcasp, MCASP_CLKDIV_AUXCLK,1387 __davinci_mcasp_set_clkdiv(mcasp, auxclk_div_id,
1172 aux_div, 0);1388 aux_div, false);
1173 }1389 }
1174 1390
1175 return error_ppm;1391 return error_ppm;
@@ -1220,6 +1436,7 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, · 44 unmodified lines
1220 int channels = params_channels(params);1436 int channels = params_channels(params);
1221 int period_size = params_period_size(params);1437 int period_size = params_period_size(params);
1222 int ret;1438 int ret;
1439 unsigned int sysclk_freq = mcasp_get_sysclk_freq(mcasp, substream->stream);
1223 1440
1224 switch (params_format(params)) {1441 switch (params_format(params)) {
1225 case SNDRV_PCM_FORMAT_U8: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 * If mcasp is BCLK master, and a BCLK divider was not provided by1477 * If mcasp is BCLK master, and a BCLK divider was not provided by
1261 * the machine driver, we need to calculate the ratio.1478 * the machine driver, we need to calculate the ratio.
1262 */1479 */
1263 if (mcasp->bclk_master && mcasp->bclk_div == 0 && mcasp->sysclk_freq) {1480 if (mcasp->bclk_master && mcasp_get_bclk_div(mcasp, substream->stream) == 0 &&
1264 int slots = mcasp->tdm_slots;1481 sysclk_freq) {
1482 int slots, slot_width;
1265 int rate = params_rate(params);1483 int rate = params_rate(params);
1266 int sbits = params_width(params);1484 int sbits = params_width(params);
1267 unsigned int bclk_target;1485 unsigned int bclk_target;
1268 1486
1269 if (mcasp->slot_width)1487 slots = mcasp_get_tdm_slots(mcasp, substream->stream);
1270 sbits = mcasp->slot_width;1488
1489 slot_width = mcasp_get_slot_width(mcasp, substream->stream);
1490 if (slot_width)
1491 sbits = slot_width;
1271 1492
1272 if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE)1493 if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE)
1273 bclk_target = rate * sbits * slots;1494 bclk_target = rate * sbits * slots;
1274 else1495 else
1275 bclk_target = rate * 128;1496 bclk_target = rate * 128;
1276 1497
1277 davinci_mcasp_calc_clk_div(mcasp, mcasp->sysclk_freq,1498 davinci_mcasp_calc_clk_div(mcasp, sysclk_freq,
1278 bclk_target, true);1499 bclk_target, substream->stream, true);
1279 }1500 }
1280 1501
1281 ret = mcasp_common_hw_param(mcasp, substream->stream,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 if (ret)1513 if (ret)
1293 return ret;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 mcasp->channels = channels;1520 mcasp->channels = channels;
1299 if (!mcasp->max_format_width)1521 if (!mcasp->max_format_width)
1300 mcasp->max_format_width = word_length;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 snd_pcm_format_t i;1560 snd_pcm_format_t i;
1339 1561
1340 snd_mask_none(&nfmt);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 pcm_for_each_format(i) {1565 pcm_for_each_format(i) {
1344 if (snd_mask_test_format(fmt, i)) {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 struct snd_interval *ri =1610 struct snd_interval *ri =
1389 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);1611 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
1390 int sbits = params_width(params);1612 int sbits = params_width(params);
1391 int slots = rd->mcasp->tdm_slots;1613 int slots, slot_width;
1392 struct snd_interval range;1614 struct snd_interval range;
1393 int i;1615 int i;
1394 1616
1395 if (rd->mcasp->slot_width)1617 slots = mcasp_get_tdm_slots(rd->mcasp, rd->stream);
1396 sbits = rd->mcasp->slot_width;1618
1619 slot_width = mcasp_get_slot_width(rd->mcasp, rd->stream);
1620 if (slot_width)
1621 sbits = slot_width;
1397 1622
1398 snd_interval_any(&range);1623 snd_interval_any(&range);
1399 range.empty = 1;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 uint bclk_freq = sbits * slots *1628 uint bclk_freq = sbits * slots *
1404 davinci_mcasp_dai_rates[i];1629 davinci_mcasp_dai_rates[i];
1405 unsigned int sysclk_freq;1630 unsigned int sysclk_freq;
1631 unsigned int ratio;
1406 int ppm;1632 int ppm;
1407 1633
1408 if (rd->mcasp->auxclk_fs_ratio)1634 ratio = mcasp_get_auxclk_fs_ratio(rd->mcasp, rd->stream);
1409 sysclk_freq = davinci_mcasp_dai_rates[i] *1635 if (ratio)
1410 rd->mcasp->auxclk_fs_ratio;1636 sysclk_freq = davinci_mcasp_dai_rates[i] * ratio;
1411 else1637 else
1412 sysclk_freq = rd->mcasp->sysclk_freq;1638 sysclk_freq = mcasp_get_sysclk_freq(rd->mcasp, rd->stream);
1413 1639
1414 ppm = davinci_mcasp_calc_clk_div(rd->mcasp, sysclk_freq,1640 ppm = davinci_mcasp_calc_clk_div(rd->mcasp, sysclk_freq,
1415 bclk_freq, false);1641 bclk_freq, rd->stream, false);
1416 if (abs(ppm) < DAVINCI_MAX_RATE_ERROR_PPM) {1642 if (abs(ppm) < DAVINCI_MAX_RATE_ERROR_PPM) {
1417 if (range.empty) {1643 if (range.empty) {
1418 range.min = davinci_mcasp_dai_rates[i];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 struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);1664 struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
1439 struct snd_mask nfmt;1665 struct snd_mask nfmt;
1440 int rate = params_rate(params);1666 int rate = params_rate(params);
1441 int slots = rd->mcasp->tdm_slots;1667 int slots;
1442 int count = 0;1668 int count = 0;
1443 snd_pcm_format_t i;1669 snd_pcm_format_t i;
1444 1670
1671 slots = mcasp_get_tdm_slots(rd->mcasp, rd->stream);
1672
1445 snd_mask_none(&nfmt);1673 snd_mask_none(&nfmt);
1446 1674
1447 pcm_for_each_format(i) {1675 pcm_for_each_format(i) {
1448 if (snd_mask_test_format(fmt, i)) {1676 if (snd_mask_test_format(fmt, i)) {
1449 uint sbits = snd_pcm_format_width(i);1677 uint sbits = snd_pcm_format_width(i);
1450 unsigned int sysclk_freq;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)1682 ratio = mcasp_get_auxclk_fs_ratio(rd->mcasp, rd->stream);
1454 sysclk_freq = rate *1683 if (ratio)
1455 rd->mcasp->auxclk_fs_ratio;1684 sysclk_freq = rate * ratio;
1456 else1685 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)1688 slot_width = mcasp_get_slot_width(rd->mcasp, rd->stream);
1460 sbits = rd->mcasp->slot_width;1689 if (slot_width)
1690 sbits = slot_width;
1461 1691
1462 ppm = davinci_mcasp_calc_clk_div(rd->mcasp, sysclk_freq,1692 ppm = davinci_mcasp_calc_clk_div(rd->mcasp, sysclk_freq,
1463 sbits * slots * rate,1693 sbits * slots * rate,
1464 false);1694 rd->stream, false);
1465 if (abs(ppm) < DAVINCI_MAX_RATE_ERROR_PPM) {1695 if (abs(ppm) < DAVINCI_MAX_RATE_ERROR_PPM) {
1466 snd_mask_set_format(&nfmt, i);1696 snd_mask_set_format(&nfmt, i);
1467 count++;1697 count++;
@@ -1498,7 +1728,7 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream, · 30 unmodified lines
1498 &mcasp->ruledata[substream->stream];1728 &mcasp->ruledata[substream->stream];
1499 u32 max_channels = 0;1729 u32 max_channels = 0;
1500 int i, dir, ret;1730 int i, dir, ret;
1501 int tdm_slots = mcasp->tdm_slots;1731 int tdm_slots;
1502 u8 *numevt;1732 u8 *numevt;
1503 1733
1504 /* Do not allow more then one stream per direction */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 mcasp->substreams[substream->stream] = substream;1738 mcasp->substreams[substream->stream] = substream;
1509 1739
1740 tdm_slots = mcasp_get_tdm_slots(mcasp, substream->stream);
1741
1510 if (mcasp->tdm_mask[substream->stream])1742 if (mcasp->tdm_mask[substream->stream])
1511 tdm_slots = hweight32(mcasp->tdm_mask[substream->stream]);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 ruledata->serializers = max_channels;1761 ruledata->serializers = max_channels;
1530 ruledata->mcasp = mcasp;1762 ruledata->mcasp = mcasp;
1763 ruledata->stream = substream->stream;
1531 max_channels *= tdm_slots;1764 max_channels *= tdm_slots;
1532 /*1765 /*
1533 * If the already active stream has less channels than the calculated1766 * 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 * is in use we need to use that as a constraint for the second stream.1768 * is in use we need to use that as a constraint for the second stream.
1536 * Otherwise (first stream or less allowed channels or more than one1769 * Otherwise (first stream or less allowed channels or more than one
1537 * serializer in use) we use the calculated constraint.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 if (mcasp->channels && mcasp->channels < max_channels &&1775 if (mcasp->channels && mcasp->channels < max_channels &&
1540 ruledata->serializers == 1)1776 ruledata->serializers == 1 &&
1777 !mcasp->async_mode)
1541 max_channels = mcasp->channels;1778 max_channels = mcasp->channels;
1542 /*1779 /*
1543 * But we can always allow channels upto the amount of1780 * 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 0, SNDRV_PCM_HW_PARAM_CHANNELS,1791 0, SNDRV_PCM_HW_PARAM_CHANNELS,
1555 &mcasp->chconstr[substream->stream]);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 * Only allow formats which require same amount of bits on the1796 * Only allow formats which require same amount of bits on the
1560 * bus as the currently running stream1797 * bus as the currently running stream to ensure sync mode
1561 */1798 */
1562 ret = snd_pcm_hw_rule_add(substream->runtime, 0,1799 ret = snd_pcm_hw_rule_add(substream->runtime, 0,
1563 SNDRV_PCM_HW_PARAM_FORMAT,1800 SNDRV_PCM_HW_PARAM_FORMAT,
@@ -1566,8 +1803,7 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream, · 2 unmodified lines
1566 SNDRV_PCM_HW_PARAM_FORMAT, -1);1803 SNDRV_PCM_HW_PARAM_FORMAT, -1);
1567 if (ret)1804 if (ret)
1568 return ret;1805 return ret;
1569 }1806 } else if (mcasp_get_slot_width(mcasp, substream->stream)) {
1570 else if (mcasp->slot_width) {
1571 /* Only allow formats require <= slot_width bits on the bus */1807 /* Only allow formats require <= slot_width bits on the bus */
1572 ret = snd_pcm_hw_rule_add(substream->runtime, 0,1808 ret = snd_pcm_hw_rule_add(substream->runtime, 0,
1573 SNDRV_PCM_HW_PARAM_FORMAT,1809 SNDRV_PCM_HW_PARAM_FORMAT,
@@ -1582,7 +1818,8 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream, · 8 unmodified lines
1582 * If we rely on implicit BCLK divider setting we should1818 * If we rely on implicit BCLK divider setting we should
1583 * set constraints based on what we can provide.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 ret = snd_pcm_hw_rule_add(substream->runtime, 0,1823 ret = snd_pcm_hw_rule_add(substream->runtime, 0,
1587 SNDRV_PCM_HW_PARAM_RATE,1824 SNDRV_PCM_HW_PARAM_RATE,
1588 davinci_mcasp_hw_rule_rate,1825 davinci_mcasp_hw_rule_rate,
@@ -1759,8 +1996,6 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = { · 170 unmodified lines
1759 .formats = DAVINCI_MCASP_PCM_FMTS,1996 .formats = DAVINCI_MCASP_PCM_FMTS,
1760 },1997 },
1761 .ops = &davinci_mcasp_dai_ops,1998 .ops = &davinci_mcasp_dai_ops,
1762
1763 .symmetric_rate = 1,
1764 },1999 },
1765 {2000 {
1766 .name = "davinci-mcasp.1",2001 .name = "davinci-mcasp.1",
@@ -1918,18 +2153,33 @@ static int davinci_mcasp_get_config(struct davinci_mcasp *mcasp, · 151 unmodified lines
1918 goto out;2153 goto out;
1919 }2154 }
1920 2155
2156 /* Parse TX-specific TDM slot and use it as default for RX */
1921 if (of_property_read_u32(np, "tdm-slots", &val) == 0) {2157 if (of_property_read_u32(np, "tdm-slots", &val) == 0) {
1922 if (val < 2 || val > 32) {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 return -EINVAL;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 } else if (pdata->op_mode == DAVINCI_MCASP_IIS_MODE) {2165 } else if (pdata->op_mode == DAVINCI_MCASP_IIS_MODE) {
1929 mcasp->missing_audio_param = true;2166 mcasp->missing_audio_param = true;
1930 goto out;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 of_serial_dir32 = of_get_property(np, "serial-dir", &val);2183 of_serial_dir32 = of_get_property(np, "serial-dir", &val);
1934 val /= sizeof(u32);2184 val /= sizeof(u32);
1935 if (of_serial_dir32) {2185 if (of_serial_dir32) {
@@ -1955,8 +2205,15 @@ static int davinci_mcasp_get_config(struct davinci_mcasp *mcasp, · 19 unmodified lines
1955 if (of_property_read_u32(np, "rx-num-evt", &val) == 0)2205 if (of_property_read_u32(np, "rx-num-evt", &val) == 0)
1956 pdata->rxnumevt = val;2206 pdata->rxnumevt = val;
1957 2207
1958 if (of_property_read_u32(np, "auxclk-fs-ratio", &val) == 0)2208 /* Parse TX-specific auxclk/fs ratio and use it as default for RX */
1959 mcasp->auxclk_fs_ratio = val;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 if (of_property_read_u32(np, "dismod", &val) == 0) {2218 if (of_property_read_u32(np, "dismod", &val) == 0) {
1962 if (val == 0 || val == 2 || val == 3) {2219 if (val == 0 || val == 2 || val == 3) {
@@ -1985,19 +2242,51 @@ out: · 22 unmodified lines
1985 mcasp->op_mode = pdata->op_mode;2242 mcasp->op_mode = pdata->op_mode;
1986 /* sanity check for tdm slots parameter */2243 /* sanity check for tdm slots parameter */
1987 if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE) {2244 if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE) {
1988 if (pdata->tdm_slots < 2) {2245 if (pdata->tdm_slots_tx < 2) {
1989 dev_warn(&pdev->dev, "invalid tdm slots: %d\n",2246 dev_warn(&pdev->dev, "invalid tdm tx slots: %d\n",
1990 pdata->tdm_slots);2247 pdata->tdm_slots_tx);
1991 mcasp->tdm_slots = 2;2248 mcasp->tdm_slots_tx = 2;
1992 } else if (pdata->tdm_slots > 32) {2249 } else if (pdata->tdm_slots_tx > 32) {
1993 dev_warn(&pdev->dev, "invalid tdm slots: %d\n",2250 dev_warn(&pdev->dev, "invalid tdm tx slots: %d\n",
1994 pdata->tdm_slots);2251 pdata->tdm_slots_tx);
1995 mcasp->tdm_slots = 32;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 } else {2265 } else {
1997 mcasp->tdm_slots = pdata->tdm_slots;2266 mcasp->tdm_slots_rx = pdata->tdm_slots_rx;
1998 }2267 }
1999 } else {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 mcasp->num_serializer = pdata->num_serializer;2292 mcasp->num_serializer = pdata->num_serializer;
sound/soc/ti/davinci-mcasp.h+10−0
@@ -298,10 +298,20 @@ · 297 unmodified lines
298/* Source of High-frequency transmit/receive clock */298/* Source of High-frequency transmit/receive clock */
299#define MCASP_CLK_HCLK_AHCLK 0 /* AHCLKX/R */299#define MCASP_CLK_HCLK_AHCLK 0 /* AHCLKX/R */
300#define MCASP_CLK_HCLK_AUXCLK 1 /* Internal functional clock */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/* clock divider IDs */306/* clock divider IDs */
303#define MCASP_CLKDIV_AUXCLK 0 /* HCLK divider from AUXCLK */307#define MCASP_CLKDIV_AUXCLK 0 /* HCLK divider from AUXCLK */
304#define MCASP_CLKDIV_BCLK 1 /* BCLK divider from HCLK */308#define MCASP_CLKDIV_BCLK 1 /* BCLK divider from HCLK */
305#define MCASP_CLKDIV_BCLK_FS_RATIO 2 /* to set BCLK FS ration */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#endif /* DAVINCI_MCASP_H */317#endif /* DAVINCI_MCASP_H */