Lines Matching +full:frame +full:- +full:master
1 // SPDX-License-Identifier: GPL-2.0-only
9 * based on davinci-mcasp.c DT support
31 #include "edma-pcm.h"
32 #include "davinci-i2s.h"
34 #define DRV_NAME "davinci-i2s"
39 * - This driver supports the "Audio Serial Port" (ASP),
42 * - But it labels it a "Multi-channel Buffered Serial Port"
44 * backward-compatible, possibly explaining that confusion.
46 * - OMAP chips have a controller called McBSP, which is
49 * - Newer DaVinci chips have a controller called McASP,
148 * if the codec is master and is using an unnecessarily fast bit clock
150 * entire frame at once means it can be serviced at the sample rate
169 __raw_writel(val, dev->base + reg); in davinci_mcbsp_write_reg()
174 return __raw_readl(dev->base + reg); in davinci_mcbsp_read_reg()
183 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, dev->pcr ^ m); in toggle_clock()
184 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, dev->pcr); in toggle_clock()
190 int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); in davinci_mcbsp_start()
198 if (dev->pcr & (DAVINCI_MCBSP_PCR_FSXM | DAVINCI_MCBSP_PCR_FSRM)) { in davinci_mcbsp_start()
199 /* Start frame sync */ in davinci_mcbsp_start()
209 /* Reset transmitter/receiver and sample rate/frame sync generators */ in davinci_mcbsp_stop()
228 DAVINCI_MCBSP_SRGR_FPER(DEFAULT_BITPERSAMPLE * 2 - 1) | in davinci_i2s_set_dai_fmt()
229 DAVINCI_MCBSP_SRGR_FWID(DEFAULT_BITPERSAMPLE - 1); in davinci_i2s_set_dai_fmt()
231 dev->fmt = fmt; in davinci_i2s_set_dai_fmt()
232 /* set master/slave audio interface */ in davinci_i2s_set_dai_fmt()
235 /* cpu is master */ in davinci_i2s_set_dai_fmt()
249 switch (dev->clk_input_pin) { in davinci_i2s_set_dai_fmt()
258 dev_err(dev->dev, "bad clk_input_pin\n"); in davinci_i2s_set_dai_fmt()
259 return -EINVAL; in davinci_i2s_set_dai_fmt()
264 /* codec is master */ in davinci_i2s_set_dai_fmt()
268 printk(KERN_ERR "%s:bad master\n", __func__); in davinci_i2s_set_dai_fmt()
269 return -EINVAL; in davinci_i2s_set_dai_fmt()
277 * dsp_a mode to be used with an inverted normal frame clk. in davinci_i2s_set_dai_fmt()
278 * If your codec is master and does not have contiguous in davinci_i2s_set_dai_fmt()
294 dev->mode = MOD_DSP_A; in davinci_i2s_set_dai_fmt()
297 dev->mode = MOD_DSP_B; in davinci_i2s_set_dai_fmt()
301 return -EINVAL; in davinci_i2s_set_dai_fmt()
307 * 1 - sampled on rising edge of CLKR in davinci_i2s_set_dai_fmt()
310 * 1 - clocked on falling edge of CLKX in davinci_i2s_set_dai_fmt()
312 * FSRP Receive frame sync pol, 0 - active high in davinci_i2s_set_dai_fmt()
313 * FSXP Transmit frame sync pol, 0 - active high in davinci_i2s_set_dai_fmt()
319 * 0 - sampled on falling edge of CLKR in davinci_i2s_set_dai_fmt()
322 * 0 - clocked on rising edge of CLKX in davinci_i2s_set_dai_fmt()
324 * FSRP Receive frame sync pol, 1 - active low in davinci_i2s_set_dai_fmt()
325 * FSXP Transmit frame sync pol, 1 - active low in davinci_i2s_set_dai_fmt()
331 * 1 - sampled on rising edge of CLKR in davinci_i2s_set_dai_fmt()
334 * 1 - clocked on falling edge of CLKX in davinci_i2s_set_dai_fmt()
336 * FSRP Receive frame sync pol, 1 - active low in davinci_i2s_set_dai_fmt()
337 * FSXP Transmit frame sync pol, 1 - active low in davinci_i2s_set_dai_fmt()
344 * 0 - sampled on falling edge of CLKR in davinci_i2s_set_dai_fmt()
347 * 0 - clocked on rising edge of CLKX in davinci_i2s_set_dai_fmt()
349 * FSRP Receive frame sync pol, 0 - active high in davinci_i2s_set_dai_fmt()
350 * FSXP Transmit frame sync pol, 0 - active high in davinci_i2s_set_dai_fmt()
354 return -EINVAL; in davinci_i2s_set_dai_fmt()
359 dev->pcr = pcr; in davinci_i2s_set_dai_fmt()
370 return -ENODEV; in davinci_i2s_dai_set_clkdiv()
372 dev->clk_div = div; in davinci_i2s_dai_set_clkdiv()
382 int mcbsp_word_length, master; in davinci_i2s_hw_params() local
390 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { in davinci_i2s_hw_params()
398 master = dev->fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK; in davinci_i2s_hw_params()
402 switch (master) { in davinci_i2s_hw_params()
404 freq = clk_get_rate(dev->clk); in davinci_i2s_hw_params()
408 8 - 1); in davinci_i2s_hw_params()
409 if (dev->i2s_accurate_sck) { in davinci_i2s_hw_params()
412 framesize = (freq / (--clk_div)) / in davinci_i2s_hw_params()
413 params->rate_num * in davinci_i2s_hw_params()
414 params->rate_den; in davinci_i2s_hw_params()
417 clk_div--; in davinci_i2s_hw_params()
418 srgr |= DAVINCI_MCBSP_SRGR_FPER(framesize - 1); in davinci_i2s_hw_params()
422 params->rate_num * params->rate_den; in davinci_i2s_hw_params()
424 16 - 1); in davinci_i2s_hw_params()
431 clk_div = dev->clk_div - 1; in davinci_i2s_hw_params()
432 srgr |= DAVINCI_MCBSP_SRGR_FWID(mcbsp_word_length * 8 - 1); in davinci_i2s_hw_params()
433 srgr |= DAVINCI_MCBSP_SRGR_FPER(mcbsp_word_length * 16 - 1); in davinci_i2s_hw_params()
438 /* Clock and frame sync given from external sources */ in davinci_i2s_hw_params()
441 srgr |= DAVINCI_MCBSP_SRGR_FWID(snd_interval_value(i) - 1); in davinci_i2s_hw_params()
442 pr_debug("%s - %d FWID set: re-read srgr = %X\n", in davinci_i2s_hw_params()
443 __func__, __LINE__, snd_interval_value(i) - 1); in davinci_i2s_hw_params()
446 srgr |= DAVINCI_MCBSP_SRGR_FPER(snd_interval_value(i) - 1); in davinci_i2s_hw_params()
449 return -EINVAL; in davinci_i2s_hw_params()
455 if (dev->mode == MOD_DSP_B) { in davinci_i2s_hw_params()
465 printk(KERN_WARNING "davinci-i2s: unsupported PCM format\n"); in davinci_i2s_hw_params()
466 return -EINVAL; in davinci_i2s_hw_params()
471 if (double_fmt[fmt] && dev->enable_channel_combine) { in davinci_i2s_hw_params()
475 switch (master) { in davinci_i2s_hw_params()
485 rcr |= DAVINCI_MCBSP_RCR_RFRLEN2(element_cnt - 1); in davinci_i2s_hw_params()
486 xcr |= DAVINCI_MCBSP_XCR_XFRLEN2(element_cnt - 1); in davinci_i2s_hw_params()
489 return -EINVAL; in davinci_i2s_hw_params()
494 switch (master) { in davinci_i2s_hw_params()
502 rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(element_cnt - 1); in davinci_i2s_hw_params()
503 xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(element_cnt - 1); in davinci_i2s_hw_params()
506 return -EINVAL; in davinci_i2s_hw_params()
514 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) in davinci_i2s_hw_params()
519 pr_debug("%s - %d srgr=%X\n", __func__, __LINE__, srgr); in davinci_i2s_hw_params()
520 pr_debug("%s - %d xcr=%X\n", __func__, __LINE__, xcr); in davinci_i2s_hw_params()
521 pr_debug("%s - %d rcr=%X\n", __func__, __LINE__, rcr); in davinci_i2s_hw_params()
529 int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); in davinci_i2s_prepare()
542 if (dev->pcr & (DAVINCI_MCBSP_PCR_FSXM | DAVINCI_MCBSP_PCR_FSRM | in davinci_i2s_prepare()
555 /* wait for any unexpected frame sync error to occur */ in davinci_i2s_prepare()
573 int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); in davinci_i2s_trigger()
587 ret = -EINVAL; in davinci_i2s_trigger()
596 int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); in davinci_i2s_shutdown()
610 snd_soc_dai_dma_data_set(dai, stream, &dev->dma_data[stream]); in davinci_i2s_dai_probe()
659 dev_warn(&pdev->dev, in davinci_i2s_probe()
663 dev_err(&pdev->dev, "no mem resource?\n"); in davinci_i2s_probe()
664 return -ENODEV; in davinci_i2s_probe()
668 io_base = devm_ioremap_resource(&pdev->dev, mem); in davinci_i2s_probe()
672 dev = devm_kzalloc(&pdev->dev, sizeof(struct davinci_mcbsp_dev), in davinci_i2s_probe()
675 return -ENOMEM; in davinci_i2s_probe()
677 dev->base = io_base; in davinci_i2s_probe()
680 dma_data = &dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK]; in davinci_i2s_probe()
681 dma_data->addr = (dma_addr_t)(mem->start + DAVINCI_MCBSP_DXR_REG); in davinci_i2s_probe()
685 dma = &dev->dma_request[SNDRV_PCM_STREAM_PLAYBACK]; in davinci_i2s_probe()
686 *dma = res->start; in davinci_i2s_probe()
687 dma_data->filter_data = dma; in davinci_i2s_probe()
688 } else if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) { in davinci_i2s_probe()
689 dma_data->filter_data = "tx"; in davinci_i2s_probe()
691 dev_err(&pdev->dev, "Missing DMA tx resource\n"); in davinci_i2s_probe()
692 return -ENODEV; in davinci_i2s_probe()
695 dma_data = &dev->dma_data[SNDRV_PCM_STREAM_CAPTURE]; in davinci_i2s_probe()
696 dma_data->addr = (dma_addr_t)(mem->start + DAVINCI_MCBSP_DRR_REG); in davinci_i2s_probe()
700 dma = &dev->dma_request[SNDRV_PCM_STREAM_CAPTURE]; in davinci_i2s_probe()
701 *dma = res->start; in davinci_i2s_probe()
702 dma_data->filter_data = dma; in davinci_i2s_probe()
703 } else if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) { in davinci_i2s_probe()
704 dma_data->filter_data = "rx"; in davinci_i2s_probe()
706 dev_err(&pdev->dev, "Missing DMA rx resource\n"); in davinci_i2s_probe()
707 return -ENODEV; in davinci_i2s_probe()
710 dev->clk = clk_get(&pdev->dev, NULL); in davinci_i2s_probe()
711 if (IS_ERR(dev->clk)) in davinci_i2s_probe()
712 return -ENODEV; in davinci_i2s_probe()
713 ret = clk_enable(dev->clk); in davinci_i2s_probe()
717 dev->dev = &pdev->dev; in davinci_i2s_probe()
718 dev_set_drvdata(&pdev->dev, dev); in davinci_i2s_probe()
720 ret = snd_soc_register_component(&pdev->dev, &davinci_i2s_component, in davinci_i2s_probe()
725 ret = edma_pcm_platform_register(&pdev->dev); in davinci_i2s_probe()
727 dev_err(&pdev->dev, "register PCM failed: %d\n", ret); in davinci_i2s_probe()
734 snd_soc_unregister_component(&pdev->dev); in davinci_i2s_probe()
736 clk_disable(dev->clk); in davinci_i2s_probe()
738 clk_put(dev->clk); in davinci_i2s_probe()
744 struct davinci_mcbsp_dev *dev = dev_get_drvdata(&pdev->dev); in davinci_i2s_remove()
746 snd_soc_unregister_component(&pdev->dev); in davinci_i2s_remove()
748 clk_disable(dev->clk); in davinci_i2s_remove()
749 clk_put(dev->clk); in davinci_i2s_remove()
750 dev->clk = NULL; in davinci_i2s_remove()
754 { .compatible = "ti,da850-mcbsp" },
763 .name = "davinci-mcbsp",