Lines Matching +full:tx +full:- +full:clk +full:- +full:10 +full:- +full:inverted

1 // SPDX-License-Identifier: GPL-2.0-only
9 * based on davinci-mcasp.c DT support
21 #include <linux/clk.h>
30 #include "edma-pcm.h"
31 #include "davinci-i2s.h"
33 #define DRV_NAME "davinci-i2s"
38 * - This driver supports the "Audio Serial Port" (ASP),
41 * - But it labels it a "Multi-channel Buffered Serial Port"
43 * backward-compatible, possibly explaining that confusion.
45 * - OMAP chips have a controller called McBSP, which is
48 * - Newer DaVinci chips have a controller called McASP,
101 #define DAVINCI_MCBSP_PCR_FSRM (1 << 10)
134 struct clk *clk;
135 struct clk *ext_clk;
172 __raw_writel(val, dev->base + reg);
177 return __raw_readl(dev->base + reg);
184 * So, fake it by toggling the clk polarity.
186 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, dev->pcr ^ m);
187 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, dev->pcr);
193 int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
201 if (dev->pcr & (DAVINCI_MCBSP_PCR_FSXM | DAVINCI_MCBSP_PCR_FSRM)) {
236 return -EINVAL;
247 dev_dbg(dev->dev, "slots %d, slot_width %d\n", slots, slot_width);
250 dev_err(dev->dev, "Invalid number of slots\n");
251 return -EINVAL;
254 if (rx_mask != (1 << slots) - 1) {
255 dev_err(dev->dev, "Invalid RX mask (0x%08x) : all slots must be used by McBSP\n",
257 return -EINVAL;
260 if (tx_mask != (1 << slots) - 1) {
261 dev_err(dev->dev, "Invalid TX mask (0x%08x) : all slots must be used by McBSP\n",
263 return -EINVAL;
267 dev_err(dev->dev, "%s: Unsupported slot_width %d\n", __func__, slot_width);
268 return -EINVAL;
271 dev->tdm_slots = slots;
272 dev->slot_width = slot_width;
289 DAVINCI_MCBSP_SRGR_FPER(DEFAULT_BITPERSAMPLE * 2 - 1) |
290 DAVINCI_MCBSP_SRGR_FWID(DEFAULT_BITPERSAMPLE - 1);
292 dev->fmt = fmt;
298 dev_dbg(dev->dev, "Free-running mode ON\n");
302 dev_dbg(dev->dev, "Free-running mode OFF\n");
305 dev_err(dev->dev, "Invalid clock gating\n");
306 return -EINVAL;
320 if (dev->tdm_slots || dev->slot_width) {
321 dev_err(dev->dev, "TDM is not supported for BC_FP format\n");
322 return -EINVAL;
339 if (dev->tdm_slots || dev->slot_width) {
340 dev_err(dev->dev, "TDM is not supported for BC_FC format\n");
341 return -EINVAL;
349 return -EINVAL;
357 * dsp_a mode to be used with an inverted normal frame clk.
374 dev->mode = MOD_DSP_A;
377 dev->mode = MOD_DSP_B;
381 return -EINVAL;
387 * 1 - sampled on rising edge of CLKR
390 * 1 - clocked on falling edge of CLKX
392 * FSRP Receive frame sync pol, 0 - active high
393 * FSXP Transmit frame sync pol, 0 - active high
399 * 0 - sampled on falling edge of CLKR
402 * 0 - clocked on rising edge of CLKX
404 * FSRP Receive frame sync pol, 1 - active low
405 * FSXP Transmit frame sync pol, 1 - active low
411 * 1 - sampled on rising edge of CLKR
414 * 1 - clocked on falling edge of CLKX
416 * FSRP Receive frame sync pol, 1 - active low
417 * FSXP Transmit frame sync pol, 1 - active low
424 * 0 - sampled on falling edge of CLKR
427 * 0 - clocked on rising edge of CLKX
429 * FSRP Receive frame sync pol, 0 - active high
430 * FSXP Transmit frame sync pol, 0 - active high
434 return -EINVAL;
439 dev->pcr = pcr;
450 return -ENODEV;
452 dev->clk_div = div;
483 dev_warn(dev->dev, "davinci-i2s: unsupported PCM format\n");
484 return -EINVAL;
488 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
496 master = dev->fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK;
498 if (dev->slot_width)
499 mcbsp_word_length = davinci_i2s_tdm_word_length(dev->slot_width);
508 if (dev->ext_clk) {
509 freq = clk_get_rate(dev->ext_clk);
511 freq = clk_get_rate(dev->clk);
516 8 - 1);
517 if (dev->i2s_accurate_sck) {
520 framesize = (freq / (--clk_div)) /
521 params->rate_num *
522 params->rate_den;
525 clk_div--;
526 srgr |= DAVINCI_MCBSP_SRGR_FPER(framesize - 1);
530 params->rate_num * params->rate_den;
532 16 - 1);
539 clk_div = dev->clk_div - 1;
540 srgr |= DAVINCI_MCBSP_SRGR_FWID(mcbsp_word_length * 8 - 1);
541 srgr |= DAVINCI_MCBSP_SRGR_FPER(mcbsp_word_length * 16 - 1);
546 if (dev->ext_clk) {
547 freq = clk_get_rate(dev->ext_clk);
549 freq = clk_get_rate(dev->clk);
552 if (dev->tdm_slots && dev->slot_width) {
553 clk_div = freq / (params->rate_num * params->rate_den)
554 / (dev->tdm_slots * dev->slot_width) - 1;
557 params->rate_num * params->rate_den;
566 srgr |= DAVINCI_MCBSP_SRGR_FWID(snd_interval_value(i) - 1);
567 pr_debug("%s - %d FWID set: re-read srgr = %X\n",
568 __func__, __LINE__, snd_interval_value(i) - 1);
571 srgr |= DAVINCI_MCBSP_SRGR_FPER(snd_interval_value(i) - 1);
574 return -EINVAL;
578 if (dev->mode == MOD_DSP_B) {
586 if (dev->tx_framing_bit) {
590 if (dev->rx_framing_bit) {
597 if (double_fmt[fmt] && dev->enable_channel_combine) {
611 rcr |= DAVINCI_MCBSP_RCR_RFRLEN2(element_cnt - 1);
612 xcr |= DAVINCI_MCBSP_XCR_XFRLEN2(element_cnt - 1);
615 return -EINVAL;
622 if (dev->tdm_slots > 0) {
623 rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(dev->tdm_slots - 1);
624 xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(dev->tdm_slots - 1);
632 rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(element_cnt - 1);
633 xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(element_cnt - 1);
636 return -EINVAL;
644 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
649 pr_debug("%s - %d srgr=%X\n", __func__, __LINE__, srgr);
650 pr_debug("%s - %d xcr=%X\n", __func__, __LINE__, xcr);
651 pr_debug("%s - %d rcr=%X\n", __func__, __LINE__, rcr);
659 int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
672 if (dev->pcr & (DAVINCI_MCBSP_PCR_FSXM | DAVINCI_MCBSP_PCR_FSRM |
703 int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
717 ret = -EINVAL;
726 int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
741 snd_soc_dai_dma_data_set(dai, stream, &dev->dma_data[stream]);
791 dev_warn(&pdev->dev,
795 dev_err(&pdev->dev, "no mem resource?\n");
796 return -ENODEV;
800 io_base = devm_ioremap_resource(&pdev->dev, mem);
804 dev = devm_kzalloc(&pdev->dev, sizeof(struct davinci_mcbsp_dev),
807 return -ENOMEM;
809 dev->base = io_base;
811 dev->tx_framing_bit = of_property_read_bool(pdev->dev.of_node, "ti,T1-framing-tx");
812 dev->rx_framing_bit = of_property_read_bool(pdev->dev.of_node, "ti,T1-framing-rx");
814 /* setup DMA, first TX, then RX */
815 dma_data = &dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK];
816 dma_data->addr = (dma_addr_t)(mem->start + DAVINCI_MCBSP_DXR_REG);
820 dma = &dev->dma_request[SNDRV_PCM_STREAM_PLAYBACK];
821 *dma = res->start;
822 dma_data->filter_data = dma;
823 } else if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) {
824 dma_data->filter_data = "tx";
826 dev_err(&pdev->dev, "Missing DMA tx resource\n");
827 return -ENODEV;
830 dma_data = &dev->dma_data[SNDRV_PCM_STREAM_CAPTURE];
831 dma_data->addr = (dma_addr_t)(mem->start + DAVINCI_MCBSP_DRR_REG);
835 dma = &dev->dma_request[SNDRV_PCM_STREAM_CAPTURE];
836 *dma = res->start;
837 dma_data->filter_data = dma;
838 } else if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) {
839 dma_data->filter_data = "rx";
841 dev_err(&pdev->dev, "Missing DMA rx resource\n");
842 return -ENODEV;
849 dev->clk = devm_clk_get_optional(&pdev->dev, "fck");
850 if (IS_ERR(dev->clk))
851 return dev_err_probe(&pdev->dev, PTR_ERR(dev->clk), "Invalid functional clock\n");
852 if (!dev->clk) {
853 dev->clk = devm_clk_get(&pdev->dev, NULL);
854 if (IS_ERR(dev->clk))
855 return dev_err_probe(&pdev->dev, PTR_ERR(dev->clk),
859 dev->ext_clk = devm_clk_get_optional(&pdev->dev, "clks");
860 if (IS_ERR(dev->ext_clk))
861 return dev_err_probe(&pdev->dev, PTR_ERR(dev->ext_clk), "Invalid external clock\n");
863 ret = clk_prepare_enable(dev->clk);
867 if (dev->ext_clk) {
868 dev_dbg(&pdev->dev, "External clock used for sample rate generator\n");
869 ret = clk_prepare_enable(dev->ext_clk);
871 dev_err_probe(&pdev->dev, ret, "Failed to enable external clock\n");
876 dev->dev = &pdev->dev;
877 dev_set_drvdata(&pdev->dev, dev);
879 ret = snd_soc_register_component(&pdev->dev, &davinci_i2s_component,
884 ret = edma_pcm_platform_register(&pdev->dev);
886 dev_err_probe(&pdev->dev, ret, "register PCM failed\n");
893 snd_soc_unregister_component(&pdev->dev);
895 clk_disable_unprepare(dev->ext_clk);
897 clk_disable_unprepare(dev->clk);
904 struct davinci_mcbsp_dev *dev = dev_get_drvdata(&pdev->dev);
906 snd_soc_unregister_component(&pdev->dev);
908 clk_disable_unprepare(dev->clk);
910 clk_disable_unprepare(dev->ext_clk);
914 { .compatible = "ti,da850-mcbsp" },
923 .name = "davinci-mcbsp",