Lines Matching +full:rx +full:- +full:slots

1 // SPDX-License-Identifier: GPL-2.0-only
9 * based on davinci-mcasp.c DT support
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,
172 __raw_writel(val, dev->base + reg); in davinci_mcbsp_write_reg()
177 return __raw_readl(dev->base + reg); in davinci_mcbsp_read_reg()
186 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, dev->pcr ^ m); in toggle_clock()
187 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, dev->pcr); in toggle_clock()
193 int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); in davinci_mcbsp_start()
201 if (dev->pcr & (DAVINCI_MCBSP_PCR_FSXM | DAVINCI_MCBSP_PCR_FSRM)) { in davinci_mcbsp_start()
236 return -EINVAL; in davinci_i2s_tdm_word_length()
243 int slots, int slot_width) in davinci_i2s_set_tdm_slot() argument
247 dev_dbg(dev->dev, "slots %d, slot_width %d\n", slots, slot_width); in davinci_i2s_set_tdm_slot()
249 if (slots > 128 || !slots) { in davinci_i2s_set_tdm_slot()
250 dev_err(dev->dev, "Invalid number of slots\n"); in davinci_i2s_set_tdm_slot()
251 return -EINVAL; in davinci_i2s_set_tdm_slot()
254 if (rx_mask != (1 << slots) - 1) { in davinci_i2s_set_tdm_slot()
255 dev_err(dev->dev, "Invalid RX mask (0x%08x) : all slots must be used by McBSP\n", in davinci_i2s_set_tdm_slot()
257 return -EINVAL; in davinci_i2s_set_tdm_slot()
260 if (tx_mask != (1 << slots) - 1) { in davinci_i2s_set_tdm_slot()
261 dev_err(dev->dev, "Invalid TX mask (0x%08x) : all slots must be used by McBSP\n", in davinci_i2s_set_tdm_slot()
263 return -EINVAL; in davinci_i2s_set_tdm_slot()
267 dev_err(dev->dev, "%s: Unsupported slot_width %d\n", __func__, slot_width); in davinci_i2s_set_tdm_slot()
268 return -EINVAL; in davinci_i2s_set_tdm_slot()
271 dev->tdm_slots = slots; in davinci_i2s_set_tdm_slot()
272 dev->slot_width = slot_width; in davinci_i2s_set_tdm_slot()
289 DAVINCI_MCBSP_SRGR_FPER(DEFAULT_BITPERSAMPLE * 2 - 1) | in davinci_i2s_set_dai_fmt()
290 DAVINCI_MCBSP_SRGR_FWID(DEFAULT_BITPERSAMPLE - 1); in davinci_i2s_set_dai_fmt()
292 dev->fmt = fmt; in davinci_i2s_set_dai_fmt()
298 dev_dbg(dev->dev, "Free-running mode ON\n"); in davinci_i2s_set_dai_fmt()
302 dev_dbg(dev->dev, "Free-running mode OFF\n"); in davinci_i2s_set_dai_fmt()
305 dev_err(dev->dev, "Invalid clock gating\n"); in davinci_i2s_set_dai_fmt()
306 return -EINVAL; in davinci_i2s_set_dai_fmt()
320 if (dev->tdm_slots || dev->slot_width) { in davinci_i2s_set_dai_fmt()
321 dev_err(dev->dev, "TDM is not supported for BC_FP format\n"); in davinci_i2s_set_dai_fmt()
322 return -EINVAL; in davinci_i2s_set_dai_fmt()
339 if (dev->tdm_slots || dev->slot_width) { in davinci_i2s_set_dai_fmt()
340 dev_err(dev->dev, "TDM is not supported for BC_FC format\n"); in davinci_i2s_set_dai_fmt()
341 return -EINVAL; in davinci_i2s_set_dai_fmt()
349 return -EINVAL; in davinci_i2s_set_dai_fmt()
368 * more empty bit clock slots between channels as the sample in davinci_i2s_set_dai_fmt()
374 dev->mode = MOD_DSP_A; in davinci_i2s_set_dai_fmt()
377 dev->mode = MOD_DSP_B; in davinci_i2s_set_dai_fmt()
381 return -EINVAL; in davinci_i2s_set_dai_fmt()
387 * 1 - sampled on rising edge of CLKR in davinci_i2s_set_dai_fmt()
390 * 1 - clocked on falling edge of CLKX in davinci_i2s_set_dai_fmt()
392 * FSRP Receive frame sync pol, 0 - active high in davinci_i2s_set_dai_fmt()
393 * FSXP Transmit frame sync pol, 0 - active high in davinci_i2s_set_dai_fmt()
399 * 0 - sampled on falling edge of CLKR in davinci_i2s_set_dai_fmt()
402 * 0 - clocked on rising edge of CLKX in davinci_i2s_set_dai_fmt()
404 * FSRP Receive frame sync pol, 1 - active low in davinci_i2s_set_dai_fmt()
405 * FSXP Transmit frame sync pol, 1 - active low in davinci_i2s_set_dai_fmt()
411 * 1 - sampled on rising edge of CLKR in davinci_i2s_set_dai_fmt()
414 * 1 - clocked on falling edge of CLKX in davinci_i2s_set_dai_fmt()
416 * FSRP Receive frame sync pol, 1 - active low in davinci_i2s_set_dai_fmt()
417 * FSXP Transmit frame sync pol, 1 - active low in davinci_i2s_set_dai_fmt()
424 * 0 - sampled on falling edge of CLKR in davinci_i2s_set_dai_fmt()
427 * 0 - clocked on rising edge of CLKX in davinci_i2s_set_dai_fmt()
429 * FSRP Receive frame sync pol, 0 - active high in davinci_i2s_set_dai_fmt()
430 * FSXP Transmit frame sync pol, 0 - active high in davinci_i2s_set_dai_fmt()
434 return -EINVAL; in davinci_i2s_set_dai_fmt()
439 dev->pcr = pcr; in davinci_i2s_set_dai_fmt()
450 return -ENODEV; in davinci_i2s_dai_set_clkdiv()
452 dev->clk_div = div; in davinci_i2s_dai_set_clkdiv()
483 dev_warn(dev->dev, "davinci-i2s: unsupported PCM format\n"); in davinci_i2s_hw_params()
484 return -EINVAL; in davinci_i2s_hw_params()
488 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { in davinci_i2s_hw_params()
496 master = dev->fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK; in davinci_i2s_hw_params()
498 if (dev->slot_width) in davinci_i2s_hw_params()
499 mcbsp_word_length = davinci_i2s_tdm_word_length(dev->slot_width); in davinci_i2s_hw_params()
508 if (dev->ext_clk) { in davinci_i2s_hw_params()
509 freq = clk_get_rate(dev->ext_clk); in davinci_i2s_hw_params()
511 freq = clk_get_rate(dev->clk); in davinci_i2s_hw_params()
516 8 - 1); in davinci_i2s_hw_params()
517 if (dev->i2s_accurate_sck) { in davinci_i2s_hw_params()
520 framesize = (freq / (--clk_div)) / in davinci_i2s_hw_params()
521 params->rate_num * in davinci_i2s_hw_params()
522 params->rate_den; in davinci_i2s_hw_params()
525 clk_div--; in davinci_i2s_hw_params()
526 srgr |= DAVINCI_MCBSP_SRGR_FPER(framesize - 1); in davinci_i2s_hw_params()
530 params->rate_num * params->rate_den; in davinci_i2s_hw_params()
532 16 - 1); in davinci_i2s_hw_params()
539 clk_div = dev->clk_div - 1; in davinci_i2s_hw_params()
540 srgr |= DAVINCI_MCBSP_SRGR_FWID(mcbsp_word_length * 8 - 1); in davinci_i2s_hw_params()
541 srgr |= DAVINCI_MCBSP_SRGR_FPER(mcbsp_word_length * 16 - 1); in davinci_i2s_hw_params()
546 if (dev->ext_clk) { in davinci_i2s_hw_params()
547 freq = clk_get_rate(dev->ext_clk); in davinci_i2s_hw_params()
549 freq = clk_get_rate(dev->clk); in davinci_i2s_hw_params()
552 if (dev->tdm_slots && dev->slot_width) { in davinci_i2s_hw_params()
553 clk_div = freq / (params->rate_num * params->rate_den) in davinci_i2s_hw_params()
554 / (dev->tdm_slots * dev->slot_width) - 1; in davinci_i2s_hw_params()
557 params->rate_num * params->rate_den; in davinci_i2s_hw_params()
566 srgr |= DAVINCI_MCBSP_SRGR_FWID(snd_interval_value(i) - 1); in davinci_i2s_hw_params()
567 pr_debug("%s - %d FWID set: re-read srgr = %X\n", in davinci_i2s_hw_params()
568 __func__, __LINE__, snd_interval_value(i) - 1); in davinci_i2s_hw_params()
571 srgr |= DAVINCI_MCBSP_SRGR_FPER(snd_interval_value(i) - 1); in davinci_i2s_hw_params()
574 return -EINVAL; in davinci_i2s_hw_params()
578 if (dev->mode == MOD_DSP_B) { in davinci_i2s_hw_params()
586 if (dev->tx_framing_bit) { in davinci_i2s_hw_params()
590 if (dev->rx_framing_bit) { in davinci_i2s_hw_params()
597 if (double_fmt[fmt] && dev->enable_channel_combine) { in davinci_i2s_hw_params()
611 rcr |= DAVINCI_MCBSP_RCR_RFRLEN2(element_cnt - 1); in davinci_i2s_hw_params()
612 xcr |= DAVINCI_MCBSP_XCR_XFRLEN2(element_cnt - 1); in davinci_i2s_hw_params()
615 return -EINVAL; in davinci_i2s_hw_params()
622 if (dev->tdm_slots > 0) { in davinci_i2s_hw_params()
623 rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(dev->tdm_slots - 1); in davinci_i2s_hw_params()
624 xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(dev->tdm_slots - 1); in davinci_i2s_hw_params()
632 rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(element_cnt - 1); in davinci_i2s_hw_params()
633 xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(element_cnt - 1); in davinci_i2s_hw_params()
636 return -EINVAL; in davinci_i2s_hw_params()
644 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) in davinci_i2s_hw_params()
649 pr_debug("%s - %d srgr=%X\n", __func__, __LINE__, srgr); in davinci_i2s_hw_params()
650 pr_debug("%s - %d xcr=%X\n", __func__, __LINE__, xcr); in davinci_i2s_hw_params()
651 pr_debug("%s - %d rcr=%X\n", __func__, __LINE__, rcr); in davinci_i2s_hw_params()
659 int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); in davinci_i2s_prepare()
672 if (dev->pcr & (DAVINCI_MCBSP_PCR_FSXM | DAVINCI_MCBSP_PCR_FSRM | in davinci_i2s_prepare()
703 int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); in davinci_i2s_trigger()
717 ret = -EINVAL; in davinci_i2s_trigger()
726 int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); in davinci_i2s_shutdown()
741 snd_soc_dai_dma_data_set(dai, stream, &dev->dma_data[stream]); in davinci_i2s_dai_probe()
791 dev_warn(&pdev->dev, in davinci_i2s_probe()
795 dev_err(&pdev->dev, "no mem resource?\n"); in davinci_i2s_probe()
796 return -ENODEV; in davinci_i2s_probe()
800 io_base = devm_ioremap_resource(&pdev->dev, mem); in davinci_i2s_probe()
804 dev = devm_kzalloc(&pdev->dev, sizeof(struct davinci_mcbsp_dev), in davinci_i2s_probe()
807 return -ENOMEM; in davinci_i2s_probe()
809 dev->base = io_base; in davinci_i2s_probe()
811 dev->tx_framing_bit = of_property_read_bool(pdev->dev.of_node, "ti,T1-framing-tx"); in davinci_i2s_probe()
812 dev->rx_framing_bit = of_property_read_bool(pdev->dev.of_node, "ti,T1-framing-rx"); in davinci_i2s_probe()
814 /* setup DMA, first TX, then RX */ in davinci_i2s_probe()
815 dma_data = &dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK]; in davinci_i2s_probe()
816 dma_data->addr = (dma_addr_t)(mem->start + DAVINCI_MCBSP_DXR_REG); in davinci_i2s_probe()
820 dma = &dev->dma_request[SNDRV_PCM_STREAM_PLAYBACK]; in davinci_i2s_probe()
821 *dma = res->start; in davinci_i2s_probe()
822 dma_data->filter_data = dma; in davinci_i2s_probe()
823 } else if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) { in davinci_i2s_probe()
824 dma_data->filter_data = "tx"; in davinci_i2s_probe()
826 dev_err(&pdev->dev, "Missing DMA tx resource\n"); in davinci_i2s_probe()
827 return -ENODEV; in davinci_i2s_probe()
830 dma_data = &dev->dma_data[SNDRV_PCM_STREAM_CAPTURE]; in davinci_i2s_probe()
831 dma_data->addr = (dma_addr_t)(mem->start + DAVINCI_MCBSP_DRR_REG); in davinci_i2s_probe()
835 dma = &dev->dma_request[SNDRV_PCM_STREAM_CAPTURE]; in davinci_i2s_probe()
836 *dma = res->start; in davinci_i2s_probe()
837 dma_data->filter_data = dma; in davinci_i2s_probe()
838 } else if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) { in davinci_i2s_probe()
839 dma_data->filter_data = "rx"; in davinci_i2s_probe()
841 dev_err(&pdev->dev, "Missing DMA rx resource\n"); in davinci_i2s_probe()
842 return -ENODEV; in davinci_i2s_probe()
849 dev->clk = devm_clk_get_optional(&pdev->dev, "fck"); in davinci_i2s_probe()
850 if (IS_ERR(dev->clk)) in davinci_i2s_probe()
851 return dev_err_probe(&pdev->dev, PTR_ERR(dev->clk), "Invalid functional clock\n"); in davinci_i2s_probe()
852 if (!dev->clk) { in davinci_i2s_probe()
853 dev->clk = devm_clk_get(&pdev->dev, NULL); in davinci_i2s_probe()
854 if (IS_ERR(dev->clk)) in davinci_i2s_probe()
855 return dev_err_probe(&pdev->dev, PTR_ERR(dev->clk), in davinci_i2s_probe()
859 dev->ext_clk = devm_clk_get_optional(&pdev->dev, "clks"); in davinci_i2s_probe()
860 if (IS_ERR(dev->ext_clk)) in davinci_i2s_probe()
861 return dev_err_probe(&pdev->dev, PTR_ERR(dev->ext_clk), "Invalid external clock\n"); in davinci_i2s_probe()
863 ret = clk_prepare_enable(dev->clk); in davinci_i2s_probe()
867 if (dev->ext_clk) { in davinci_i2s_probe()
868 dev_dbg(&pdev->dev, "External clock used for sample rate generator\n"); in davinci_i2s_probe()
869 ret = clk_prepare_enable(dev->ext_clk); in davinci_i2s_probe()
871 dev_err_probe(&pdev->dev, ret, "Failed to enable external clock\n"); in davinci_i2s_probe()
876 dev->dev = &pdev->dev; in davinci_i2s_probe()
877 dev_set_drvdata(&pdev->dev, dev); in davinci_i2s_probe()
879 ret = snd_soc_register_component(&pdev->dev, &davinci_i2s_component, in davinci_i2s_probe()
884 ret = edma_pcm_platform_register(&pdev->dev); in davinci_i2s_probe()
886 dev_err_probe(&pdev->dev, ret, "register PCM failed\n"); in davinci_i2s_probe()
893 snd_soc_unregister_component(&pdev->dev); in davinci_i2s_probe()
895 if (dev->ext_clk) in davinci_i2s_probe()
896 clk_disable_unprepare(dev->ext_clk); in davinci_i2s_probe()
898 clk_disable_unprepare(dev->clk); in davinci_i2s_probe()
905 struct davinci_mcbsp_dev *dev = dev_get_drvdata(&pdev->dev); in davinci_i2s_remove()
907 snd_soc_unregister_component(&pdev->dev); in davinci_i2s_remove()
909 clk_disable_unprepare(dev->clk); in davinci_i2s_remove()
911 if (dev->ext_clk) in davinci_i2s_remove()
912 clk_disable_unprepare(dev->ext_clk); in davinci_i2s_remove()
916 { .compatible = "ti,da850-mcbsp" },
925 .name = "davinci-mcbsp",