Lines Matching +full:pcm +full:- +full:clock +full:- +full:mode
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * atmel_ssc_dai.c -- ALSA SoC ATMEL SSC Audio Layer Platform driver
11 * Based on at91-ssc.c by
25 #include <linux/atmel-ssc.h>
27 #include <sound/pcm.h>
32 #include "atmel-pcm.h"
39 * SSC PDC registers required by the PCM DMA engine.
84 .name = "SSC0 PCM out",
89 .name = "SSC0 PCM in",
94 .name = "SSC1 PCM out",
99 .name = "SSC1 PCM in",
104 .name = "SSC2 PCM out",
109 .name = "SSC2 PCM in",
137 * interrupt handler in the PCM driver.
147 ssc_sr = (unsigned long)ssc_readl(ssc_p->ssc->regs, SR) in atmel_ssc_interrupt()
148 & (unsigned long)ssc_readl(ssc_p->ssc->regs, IMR); in atmel_ssc_interrupt()
152 * a DMA-related interrupt occurred on that substream, call in atmel_ssc_interrupt()
154 * registered in the dma_params structure by the PCM driver. in atmel_ssc_interrupt()
156 for (i = 0; i < ARRAY_SIZE(ssc_p->dma_params); i++) { in atmel_ssc_interrupt()
157 dma_params = ssc_p->dma_params[i]; in atmel_ssc_interrupt()
160 (dma_params->dma_intr_handler != NULL)) { in atmel_ssc_interrupt()
161 ssc_substream_mask = (dma_params->mask->ssc_endx | in atmel_ssc_interrupt()
162 dma_params->mask->ssc_endbuf); in atmel_ssc_interrupt()
164 dma_params->dma_intr_handler(ssc_sr, in atmel_ssc_interrupt()
165 dma_params-> in atmel_ssc_interrupt()
175 * When the bit clock is input, limit the maximum rate according to the
176 * Serial Clock Ratio Considerations section from the SSC documentation:
179 * with the clock signals provided on either the TK or RK pins.
180 * This allows the SSC to support many slave-mode data transfers.
181 * In this case, the maximum clock speed allowed on the RK pin is:
182 * - Peripheral clock divided by 2 if Receiver Frame Synchro is input
183 * - Peripheral clock divided by 3 if Receiver Frame Synchro is output
184 * In addition, the maximum clock speed allowed on the TK pin is:
185 * - Peripheral clock divided by 6 if Transmit Frame Synchro is input
186 * - Peripheral clock divided by 2 if Transmit Frame Synchro is output
188 * When the bit clock is output, limit the rate according to the
194 struct atmel_ssc_info *ssc_p = rule->private; in atmel_ssc_hw_rule_rate()
195 struct ssc_device *ssc = ssc_p->ssc; in atmel_ssc_hw_rule_rate()
196 struct snd_interval *i = hw_param_interval(params, rule->var); in atmel_ssc_hw_rule_rate()
212 switch (ssc_p->daifmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { in atmel_ssc_hw_rule_rate()
214 if ((ssc_p->dir_mask & SSC_DIR_MASK_CAPTURE) in atmel_ssc_hw_rule_rate()
215 && ssc->clk_from_rk_pin) in atmel_ssc_hw_rule_rate()
224 if ((ssc_p->dir_mask & SSC_DIR_MASK_PLAYBACK) in atmel_ssc_hw_rule_rate()
225 && !ssc->clk_from_rk_pin) in atmel_ssc_hw_rule_rate()
235 switch (ssc_p->daifmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { in atmel_ssc_hw_rule_rate()
237 r.num = ssc_p->mck_rate / mck_div / frame_size; in atmel_ssc_hw_rule_rate()
240 if (ret >= 0 && den && rule->var == SNDRV_PCM_HW_PARAM_RATE) { in atmel_ssc_hw_rule_rate()
241 params->rate_num = num; in atmel_ssc_hw_rule_rate()
242 params->rate_den = den; in atmel_ssc_hw_rule_rate()
249 t.max = ssc_p->mck_rate / mck_div / frame_size; in atmel_ssc_hw_rule_rate()
256 ret = -EINVAL; in atmel_ssc_hw_rule_rate()
263 /*-------------------------------------------------------------------------*\
265 \*-------------------------------------------------------------------------*/
272 struct platform_device *pdev = to_platform_device(dai->dev); in atmel_ssc_startup()
273 struct atmel_ssc_info *ssc_p = &ssc_info[pdev->id]; in atmel_ssc_startup()
279 ssc_readl(ssc_p->ssc->regs, SR)); in atmel_ssc_startup()
281 /* Enable PMC peripheral clock for this SSC */ in atmel_ssc_startup()
282 pr_debug("atmel_ssc_dai: Starting clock\n"); in atmel_ssc_startup()
283 ret = clk_enable(ssc_p->ssc->clk); in atmel_ssc_startup()
287 ssc_p->mck_rate = clk_get_rate(ssc_p->ssc->clk); in atmel_ssc_startup()
290 if (!ssc_p->initialized) in atmel_ssc_startup()
291 ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST)); in atmel_ssc_startup()
293 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { in atmel_ssc_startup()
301 ret = snd_pcm_hw_rule_add(substream->runtime, 0, in atmel_ssc_startup()
306 SNDRV_PCM_HW_PARAM_CHANNELS, -1); in atmel_ssc_startup()
308 dev_err(dai->dev, "Failed to specify rate rule: %d\n", ret); in atmel_ssc_startup()
312 dma_params = &ssc_dma_params[pdev->id][dir]; in atmel_ssc_startup()
313 dma_params->ssc = ssc_p->ssc; in atmel_ssc_startup()
314 dma_params->substream = substream; in atmel_ssc_startup()
316 ssc_p->dma_params[dir] = dma_params; in atmel_ssc_startup()
320 if (ssc_p->dir_mask & dir_mask) in atmel_ssc_startup()
321 return -EBUSY; in atmel_ssc_startup()
323 ssc_p->dir_mask |= dir_mask; in atmel_ssc_startup()
335 struct platform_device *pdev = to_platform_device(dai->dev); in atmel_ssc_shutdown()
336 struct atmel_ssc_info *ssc_p = &ssc_info[pdev->id]; in atmel_ssc_shutdown()
340 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) in atmel_ssc_shutdown()
345 dma_params = ssc_p->dma_params[dir]; in atmel_ssc_shutdown()
348 dma_params->ssc = NULL; in atmel_ssc_shutdown()
349 dma_params->substream = NULL; in atmel_ssc_shutdown()
350 ssc_p->dma_params[dir] = NULL; in atmel_ssc_shutdown()
355 ssc_p->dir_mask &= ~dir_mask; in atmel_ssc_shutdown()
356 if (!ssc_p->dir_mask) { in atmel_ssc_shutdown()
357 if (ssc_p->initialized) { in atmel_ssc_shutdown()
358 free_irq(ssc_p->ssc->irq, ssc_p); in atmel_ssc_shutdown()
359 ssc_p->initialized = 0; in atmel_ssc_shutdown()
363 ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST)); in atmel_ssc_shutdown()
365 ssc_p->cmr_div = ssc_p->tcmr_period = ssc_p->rcmr_period = 0; in atmel_ssc_shutdown()
366 ssc_p->forced_divider = 0; in atmel_ssc_shutdown()
369 /* Shutdown the SSC clock. */ in atmel_ssc_shutdown()
370 pr_debug("atmel_ssc_dai: Stopping clock\n"); in atmel_ssc_shutdown()
371 clk_disable(ssc_p->ssc->clk); in atmel_ssc_shutdown()
381 struct platform_device *pdev = to_platform_device(cpu_dai->dev); in atmel_ssc_set_dai_fmt()
382 struct atmel_ssc_info *ssc_p = &ssc_info[pdev->id]; in atmel_ssc_set_dai_fmt()
384 ssc_p->daifmt = fmt; in atmel_ssc_set_dai_fmt()
389 * Record SSC clock dividers for use in hw_params().
394 struct platform_device *pdev = to_platform_device(cpu_dai->dev); in atmel_ssc_set_dai_clkdiv()
395 struct atmel_ssc_info *ssc_p = &ssc_info[pdev->id]; in atmel_ssc_set_dai_clkdiv()
400 * The same master clock divider is used for both in atmel_ssc_set_dai_clkdiv()
404 if (ssc_p->dir_mask != in atmel_ssc_set_dai_clkdiv()
406 ssc_p->cmr_div = div; in atmel_ssc_set_dai_clkdiv()
407 else if (ssc_p->cmr_div == 0) in atmel_ssc_set_dai_clkdiv()
408 ssc_p->cmr_div = div; in atmel_ssc_set_dai_clkdiv()
410 if (div != ssc_p->cmr_div) in atmel_ssc_set_dai_clkdiv()
411 return -EBUSY; in atmel_ssc_set_dai_clkdiv()
412 ssc_p->forced_divider |= BIT(ATMEL_SSC_CMR_DIV); in atmel_ssc_set_dai_clkdiv()
416 ssc_p->tcmr_period = div; in atmel_ssc_set_dai_clkdiv()
417 ssc_p->forced_divider |= BIT(ATMEL_SSC_TCMR_PERIOD); in atmel_ssc_set_dai_clkdiv()
421 ssc_p->rcmr_period = div; in atmel_ssc_set_dai_clkdiv()
422 ssc_p->forced_divider |= BIT(ATMEL_SSC_RCMR_PERIOD); in atmel_ssc_set_dai_clkdiv()
426 return -EINVAL; in atmel_ssc_set_dai_clkdiv()
432 /* Is the cpu-dai master of the frame clock? */
435 switch (ssc_p->daifmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { in atmel_ssc_cfs()
443 /* Is the cpu-dai master of the bit clock? */
446 switch (ssc_p->daifmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { in atmel_ssc_cbs()
461 struct platform_device *pdev = to_platform_device(dai->dev); in atmel_ssc_hw_params()
462 int id = pdev->id; in atmel_ssc_hw_params()
464 struct ssc_device *ssc = ssc_p->ssc; in atmel_ssc_hw_params()
479 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) in atmel_ssc_hw_params()
488 cmr_div = ssc_p->cmr_div; in atmel_ssc_hw_params()
489 if (!(ssc_p->forced_divider & BIT(ATMEL_SSC_CMR_DIV)) && in atmel_ssc_hw_params()
494 dev_err(dai->dev, "unable to calculate cmr_div: %d\n", in atmel_ssc_hw_params()
499 cmr_div = DIV_ROUND_CLOSEST(ssc_p->mck_rate, 2 * bclk_rate); in atmel_ssc_hw_params()
506 tcmr_period = ssc_p->tcmr_period; in atmel_ssc_hw_params()
507 rcmr_period = ssc_p->rcmr_period; in atmel_ssc_hw_params()
512 dev_err(dai->dev, in atmel_ssc_hw_params()
518 if (!(ssc_p->forced_divider & BIT(ATMEL_SSC_TCMR_PERIOD))) in atmel_ssc_hw_params()
519 tcmr_period = frame_size / 2 - 1; in atmel_ssc_hw_params()
520 if (!(ssc_p->forced_divider & BIT(ATMEL_SSC_RCMR_PERIOD))) in atmel_ssc_hw_params()
521 rcmr_period = frame_size / 2 - 1; in atmel_ssc_hw_params()
524 dma_params = ssc_p->dma_params[dir]; in atmel_ssc_hw_params()
534 dma_params->pdc_xfer_size = 1; in atmel_ssc_hw_params()
538 dma_params->pdc_xfer_size = 2; in atmel_ssc_hw_params()
542 dma_params->pdc_xfer_size = 4; in atmel_ssc_hw_params()
546 dma_params->pdc_xfer_size = 4; in atmel_ssc_hw_params()
549 printk(KERN_WARNING "atmel_ssc_dai: unsupported PCM format"); in atmel_ssc_hw_params()
550 return -EINVAL; in atmel_ssc_hw_params()
557 fslen_ext = (bits - 1) / 16; in atmel_ssc_hw_params()
558 fslen = (bits - 1) % 16; in atmel_ssc_hw_params()
560 switch (ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) { in atmel_ssc_hw_params()
582 * DSP/PCM Mode A format in atmel_ssc_hw_params()
599 ssc_p->daifmt); in atmel_ssc_hw_params()
600 return -EINVAL; in atmel_ssc_hw_params()
626 rcmr |= SSC_BF(RCMR_CKS, ssc->clk_from_rk_pin ? in atmel_ssc_hw_params()
630 tcmr |= SSC_BF(TCMR_CKS, ssc->clk_from_rk_pin ? in atmel_ssc_hw_params()
645 | SSC_BF(RFMR_DATNB, (channels - 1)) in atmel_ssc_hw_params()
648 | SSC_BF(RFMR_DATLEN, (bits - 1)); in atmel_ssc_hw_params()
655 | SSC_BF(TFMR_DATNB, (channels - 1)) in atmel_ssc_hw_params()
658 | SSC_BF(TFMR_DATLEN, (bits - 1)); in atmel_ssc_hw_params()
660 if (fslen_ext && !ssc->pdata->has_fslen_ext) { in atmel_ssc_hw_params()
661 dev_err(dai->dev, "sample size %d is too large for SSC device\n", in atmel_ssc_hw_params()
663 return -EINVAL; in atmel_ssc_hw_params()
670 if (!ssc_p->initialized) { in atmel_ssc_hw_params()
671 if (!ssc_p->ssc->pdata->use_dma) { in atmel_ssc_hw_params()
672 ssc_writel(ssc_p->ssc->regs, PDC_RPR, 0); in atmel_ssc_hw_params()
673 ssc_writel(ssc_p->ssc->regs, PDC_RCR, 0); in atmel_ssc_hw_params()
674 ssc_writel(ssc_p->ssc->regs, PDC_RNPR, 0); in atmel_ssc_hw_params()
675 ssc_writel(ssc_p->ssc->regs, PDC_RNCR, 0); in atmel_ssc_hw_params()
677 ssc_writel(ssc_p->ssc->regs, PDC_TPR, 0); in atmel_ssc_hw_params()
678 ssc_writel(ssc_p->ssc->regs, PDC_TCR, 0); in atmel_ssc_hw_params()
679 ssc_writel(ssc_p->ssc->regs, PDC_TNPR, 0); in atmel_ssc_hw_params()
680 ssc_writel(ssc_p->ssc->regs, PDC_TNCR, 0); in atmel_ssc_hw_params()
683 ret = request_irq(ssc_p->ssc->irq, atmel_ssc_interrupt, 0, in atmel_ssc_hw_params()
684 ssc_p->name, ssc_p); in atmel_ssc_hw_params()
688 pr_debug("Atmel_ssc_dai: Stopping clock\n"); in atmel_ssc_hw_params()
689 clk_disable(ssc_p->ssc->clk); in atmel_ssc_hw_params()
693 ssc_p->initialized = 1; in atmel_ssc_hw_params()
696 /* set SSC clock mode register */ in atmel_ssc_hw_params()
697 ssc_writel(ssc_p->ssc->regs, CMR, cmr_div); in atmel_ssc_hw_params()
699 /* set receive clock mode and format */ in atmel_ssc_hw_params()
700 ssc_writel(ssc_p->ssc->regs, RCMR, rcmr); in atmel_ssc_hw_params()
701 ssc_writel(ssc_p->ssc->regs, RFMR, rfmr); in atmel_ssc_hw_params()
703 /* set transmit clock mode and format */ in atmel_ssc_hw_params()
704 ssc_writel(ssc_p->ssc->regs, TCMR, tcmr); in atmel_ssc_hw_params()
705 ssc_writel(ssc_p->ssc->regs, TFMR, tfmr); in atmel_ssc_hw_params()
715 struct platform_device *pdev = to_platform_device(dai->dev); in atmel_ssc_prepare()
716 struct atmel_ssc_info *ssc_p = &ssc_info[pdev->id]; in atmel_ssc_prepare()
720 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) in atmel_ssc_prepare()
725 dma_params = ssc_p->dma_params[dir]; in atmel_ssc_prepare()
727 ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_disable); in atmel_ssc_prepare()
728 ssc_writel(ssc_p->ssc->regs, IDR, dma_params->mask->ssc_error); in atmel_ssc_prepare()
732 ssc_readl(ssc_p->ssc->regs, SR)); in atmel_ssc_prepare()
739 struct platform_device *pdev = to_platform_device(dai->dev); in atmel_ssc_trigger()
740 struct atmel_ssc_info *ssc_p = &ssc_info[pdev->id]; in atmel_ssc_trigger()
744 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) in atmel_ssc_trigger()
749 dma_params = ssc_p->dma_params[dir]; in atmel_ssc_trigger()
755 ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_enable); in atmel_ssc_trigger()
758 ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_disable); in atmel_ssc_trigger()
768 struct platform_device *pdev = to_platform_device(component->dev); in atmel_ssc_suspend()
773 ssc_p = &ssc_info[pdev->id]; in atmel_ssc_suspend()
776 ssc_p->ssc_state.ssc_sr = ssc_readl(ssc_p->ssc->regs, SR); in atmel_ssc_suspend()
777 ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_TXDIS) | SSC_BIT(CR_RXDIS)); in atmel_ssc_suspend()
780 ssc_p->ssc_state.ssc_imr = ssc_readl(ssc_p->ssc->regs, IMR); in atmel_ssc_suspend()
781 ssc_writel(ssc_p->ssc->regs, IDR, ssc_p->ssc_state.ssc_imr); in atmel_ssc_suspend()
783 ssc_p->ssc_state.ssc_cmr = ssc_readl(ssc_p->ssc->regs, CMR); in atmel_ssc_suspend()
784 ssc_p->ssc_state.ssc_rcmr = ssc_readl(ssc_p->ssc->regs, RCMR); in atmel_ssc_suspend()
785 ssc_p->ssc_state.ssc_rfmr = ssc_readl(ssc_p->ssc->regs, RFMR); in atmel_ssc_suspend()
786 ssc_p->ssc_state.ssc_tcmr = ssc_readl(ssc_p->ssc->regs, TCMR); in atmel_ssc_suspend()
787 ssc_p->ssc_state.ssc_tfmr = ssc_readl(ssc_p->ssc->regs, TFMR); in atmel_ssc_suspend()
795 struct platform_device *pdev = to_platform_device(component->dev); in atmel_ssc_resume()
801 ssc_p = &ssc_info[pdev->id]; in atmel_ssc_resume()
804 ssc_writel(ssc_p->ssc->regs, TFMR, ssc_p->ssc_state.ssc_tfmr); in atmel_ssc_resume()
805 ssc_writel(ssc_p->ssc->regs, TCMR, ssc_p->ssc_state.ssc_tcmr); in atmel_ssc_resume()
806 ssc_writel(ssc_p->ssc->regs, RFMR, ssc_p->ssc_state.ssc_rfmr); in atmel_ssc_resume()
807 ssc_writel(ssc_p->ssc->regs, RCMR, ssc_p->ssc_state.ssc_rcmr); in atmel_ssc_resume()
808 ssc_writel(ssc_p->ssc->regs, CMR, ssc_p->ssc_state.ssc_cmr); in atmel_ssc_resume()
810 /* re-enable interrupts */ in atmel_ssc_resume()
811 ssc_writel(ssc_p->ssc->regs, IER, ssc_p->ssc_state.ssc_imr); in atmel_ssc_resume()
813 /* Re-enable receive and transmit as appropriate */ in atmel_ssc_resume()
816 (ssc_p->ssc_state.ssc_sr & SSC_BIT(SR_RXEN)) ? SSC_BIT(CR_RXEN) : 0; in atmel_ssc_resume()
818 (ssc_p->ssc_state.ssc_sr & SSC_BIT(SR_TXEN)) ? SSC_BIT(CR_TXEN) : 0; in atmel_ssc_resume()
819 ssc_writel(ssc_p->ssc->regs, CR, cr); in atmel_ssc_resume()
859 .name = "atmel-ssc",
877 if (ssc->pdata->use_dma) in asoc_ssc_init()
883 dev_err(dev, "Could not register PCM: %d\n", ret); in asoc_ssc_init()
891 * atmel_ssc_set_audio - Allocate the specified SSC for audio use.
908 return asoc_ssc_init(&ssc->pdev->dev); in atmel_ssc_set_audio()