Lines Matching +full:capture +full:- +full:channels

1 // SPDX-License-Identifier: GPL-2.0
3 // Renesas RZ/G2L ASoC Serial Sound Interface (SSIF-2) Driver
74 #define SSI_RATES SNDRV_PCM_RATE_8000_48000 /* 8k-44.1kHz */
116 * The SSI supports full-duplex transmission and reception.
119 * So it is better to use as half-duplex (playing and recording
120 * should be done on separate channels).
123 struct rz_ssi_stream capture; member
139 writel(data, (priv->base + reg)); in rz_ssi_reg_writel()
144 return readl(priv->base + reg); in rz_ssi_reg_readl()
152 val = readl(priv->base + reg); in rz_ssi_reg_mask_setl()
154 writel(val, (priv->base + reg)); in rz_ssi_reg_mask_setl()
168 return substream->stream == SNDRV_PCM_STREAM_PLAYBACK; in rz_ssi_stream_is_play()
174 struct rz_ssi_stream *stream = &ssi->playback; in rz_ssi_stream_get()
176 if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) in rz_ssi_stream_get()
177 stream = &ssi->capture; in rz_ssi_stream_get()
184 return (ssi->playback.dma_ch && (ssi->dma_rt || ssi->capture.dma_ch)); in rz_ssi_is_dma_enabled()
190 struct rz_ssi_priv *ssi = strm->priv; in rz_ssi_set_substream()
193 spin_lock_irqsave(&ssi->lock, flags); in rz_ssi_set_substream()
194 strm->substream = substream; in rz_ssi_set_substream()
195 spin_unlock_irqrestore(&ssi->lock, flags); in rz_ssi_set_substream()
204 spin_lock_irqsave(&ssi->lock, flags); in rz_ssi_stream_is_valid()
205 ret = strm->substream && strm->substream->runtime; in rz_ssi_stream_is_valid()
206 spin_unlock_irqrestore(&ssi->lock, flags); in rz_ssi_stream_is_valid()
214 struct snd_pcm_runtime *runtime = substream->runtime; in rz_ssi_stream_init()
217 strm->sample_width = samples_to_bytes(runtime, 1); in rz_ssi_stream_init()
218 strm->dma_buffer_pos = 0; in rz_ssi_stream_init()
219 strm->period_counter = 0; in rz_ssi_stream_init()
220 strm->buffer_pos = 0; in rz_ssi_stream_init()
222 strm->oerr_num = 0; in rz_ssi_stream_init()
223 strm->uerr_num = 0; in rz_ssi_stream_init()
224 strm->running = 0; in rz_ssi_stream_init()
227 strm->fifo_sample_size = SSI_FIFO_DEPTH; in rz_ssi_stream_init()
233 struct snd_soc_dai *dai = rz_ssi_get_dai(strm->substream); in rz_ssi_stream_quit()
237 if (strm->oerr_num > 0) in rz_ssi_stream_quit()
238 dev_info(dai->dev, "overrun = %d\n", strm->oerr_num); in rz_ssi_stream_quit()
240 if (strm->uerr_num > 0) in rz_ssi_stream_quit()
241 dev_info(dai->dev, "underrun = %d\n", strm->uerr_num); in rz_ssi_stream_quit()
245 unsigned int channels) in rz_ssi_clk_setup() argument
248 6, 12, 24, 48, 96, -1, -1, -1 }; in rz_ssi_clk_setup()
250 unsigned long bclk_rate = rate * channels * channel_bits; in rz_ssi_clk_setup()
261 if (ssi->audio_clk_1 && ssi->audio_clk_2) { in rz_ssi_clk_setup()
262 if (ssi->audio_clk_1 % bclk_rate) in rz_ssi_clk_setup()
263 ssi->audio_mck = ssi->audio_clk_2; in rz_ssi_clk_setup()
265 ssi->audio_mck = ssi->audio_clk_1; in rz_ssi_clk_setup()
270 if (ssi->audio_mck == ssi->audio_clk_1) in rz_ssi_clk_setup()
272 if (ssi->bckp_rise) in rz_ssi_clk_setup()
274 if (ssi->lrckp_fsync_fall) in rz_ssi_clk_setup()
279 div = ssi->audio_mck / bclk_rate; in rz_ssi_clk_setup()
289 dev_err(ssi->dev, "Rate not divisible by audio clock source\n"); in rz_ssi_clk_setup()
290 return -EINVAL; in rz_ssi_clk_setup()
308 bool is_play = rz_ssi_stream_is_play(ssi, strm->substream); in rz_ssi_start()
319 SSISCR_TDES(strm->fifo_sample_size / 2 - 1) | in rz_ssi_start()
339 strm->running = 1; in rz_ssi_start()
350 strm->running = 0; in rz_ssi_stop()
357 dmaengine_terminate_async(strm->dma_ch); in rz_ssi_stop()
371 while (--timeout) { in rz_ssi_stop()
378 dev_info(ssi->dev, "timeout waiting for SSI idle\n"); in rz_ssi_stop()
389 struct snd_pcm_substream *substream = strm->substream; in rz_ssi_pointer_update()
393 if (!strm->running || !substream || !substream->runtime) in rz_ssi_pointer_update()
396 runtime = substream->runtime; in rz_ssi_pointer_update()
397 strm->buffer_pos += frames; in rz_ssi_pointer_update()
398 WARN_ON(strm->buffer_pos > runtime->buffer_size); in rz_ssi_pointer_update()
401 if (strm->buffer_pos == runtime->buffer_size) in rz_ssi_pointer_update()
402 strm->buffer_pos = 0; in rz_ssi_pointer_update()
404 current_period = strm->buffer_pos / runtime->period_size; in rz_ssi_pointer_update()
405 if (strm->period_counter != current_period) { in rz_ssi_pointer_update()
406 snd_pcm_period_elapsed(strm->substream); in rz_ssi_pointer_update()
407 strm->period_counter = current_period; in rz_ssi_pointer_update()
413 struct snd_pcm_substream *substream = strm->substream; in rz_ssi_pio_recv()
422 return -EINVAL; in rz_ssi_pio_recv()
424 runtime = substream->runtime; in rz_ssi_pio_recv()
428 frames_left = runtime->period_size - in rz_ssi_pio_recv()
429 (strm->buffer_pos % runtime->period_size); in rz_ssi_pio_recv()
431 frames_left = runtime->period_size; in rz_ssi_pio_recv()
439 while (frames_left && (fifo_samples >= runtime->channels)) { in rz_ssi_pio_recv()
440 samples += runtime->channels; in rz_ssi_pio_recv()
441 fifo_samples -= runtime->channels; in rz_ssi_pio_recv()
442 frames_left--; in rz_ssi_pio_recv()
450 buf = (u16 *)runtime->dma_area; in rz_ssi_pio_recv()
451 buf += strm->buffer_pos * runtime->channels; in rz_ssi_pio_recv()
453 /* Note, only supports 16-bit samples */ in rz_ssi_pio_recv()
458 rz_ssi_pointer_update(strm, samples / runtime->channels); in rz_ssi_pio_recv()
459 } while (!frames_left && fifo_samples >= runtime->channels); in rz_ssi_pio_recv()
466 struct snd_pcm_substream *substream = strm->substream; in rz_ssi_pio_send()
467 struct snd_pcm_runtime *runtime = substream->runtime; in rz_ssi_pio_send()
476 return -EINVAL; in rz_ssi_pio_send()
479 frames_left = runtime->period_size - (strm->buffer_pos % in rz_ssi_pio_send()
480 runtime->period_size); in rz_ssi_pio_send()
482 frames_left = runtime->period_size; in rz_ssi_pio_send()
484 sample_space = strm->fifo_sample_size; in rz_ssi_pio_send()
486 sample_space -= (ssifsr >> SSIFSR_TDC_SHIFT) & SSIFSR_TDC_MASK; in rz_ssi_pio_send()
489 while (frames_left && (sample_space >= runtime->channels)) { in rz_ssi_pio_send()
490 samples += runtime->channels; in rz_ssi_pio_send()
491 sample_space -= runtime->channels; in rz_ssi_pio_send()
492 frames_left--; in rz_ssi_pio_send()
500 buf = (u16 *)(runtime->dma_area); in rz_ssi_pio_send()
501 buf += strm->buffer_pos * runtime->channels; in rz_ssi_pio_send()
503 /* Note, only supports 16-bit samples */ in rz_ssi_pio_send()
508 rz_ssi_pointer_update(strm, samples / runtime->channels); in rz_ssi_pio_send()
519 if (ssi->playback.substream) in rz_ssi_interrupt()
520 strm = &ssi->playback; in rz_ssi_interrupt()
521 else if (ssi->capture.substream) in rz_ssi_interrupt()
522 strm = &ssi->capture; in rz_ssi_interrupt()
526 if (irq == ssi->irq_int) { /* error or idle */ in rz_ssi_interrupt()
528 strm->uerr_num++; in rz_ssi_interrupt()
530 strm->oerr_num++; in rz_ssi_interrupt()
532 strm->uerr_num++; in rz_ssi_interrupt()
534 strm->oerr_num++; in rz_ssi_interrupt()
548 strm->transfer(ssi, strm); in rz_ssi_interrupt()
555 if (!strm->running) in rz_ssi_interrupt()
559 if (irq == ssi->irq_tx) in rz_ssi_interrupt()
560 strm->transfer(ssi, &ssi->playback); in rz_ssi_interrupt()
563 if (irq == ssi->irq_rx) { in rz_ssi_interrupt()
564 strm->transfer(ssi, &ssi->capture); in rz_ssi_interrupt()
579 cfg.dst_addr = ssi->phys + SSIFTDR; in rz_ssi_dma_slave_config()
580 cfg.src_addr = ssi->phys + SSIFRDR; in rz_ssi_dma_slave_config()
590 struct snd_pcm_substream *substream = strm->substream; in rz_ssi_dma_transfer()
598 return -EINVAL; in rz_ssi_dma_transfer()
600 runtime = substream->runtime; in rz_ssi_dma_transfer()
601 if (runtime->state == SNDRV_PCM_STATE_DRAINING) in rz_ssi_dma_transfer()
612 amount = runtime->period_size; in rz_ssi_dma_transfer()
615 dma_paddr = runtime->dma_addr + frames_to_bytes(runtime, in rz_ssi_dma_transfer()
616 strm->dma_buffer_pos); in rz_ssi_dma_transfer()
618 desc = dmaengine_prep_slave_single(strm->dma_ch, dma_paddr, dma_size, in rz_ssi_dma_transfer()
622 dev_err(ssi->dev, "dmaengine_prep_slave_single() fail\n"); in rz_ssi_dma_transfer()
623 return -ENOMEM; in rz_ssi_dma_transfer()
626 desc->callback = rz_ssi_dma_complete; in rz_ssi_dma_transfer()
627 desc->callback_param = strm; in rz_ssi_dma_transfer()
630 dev_err(ssi->dev, "dmaengine_submit() fail\n"); in rz_ssi_dma_transfer()
631 return -EIO; in rz_ssi_dma_transfer()
635 strm->dma_buffer_pos += amount; in rz_ssi_dma_transfer()
636 if (strm->dma_buffer_pos >= runtime->buffer_size) in rz_ssi_dma_transfer()
637 strm->dma_buffer_pos = 0; in rz_ssi_dma_transfer()
640 dma_async_issue_pending(strm->dma_ch); in rz_ssi_dma_transfer()
649 if (!strm->running || !strm->substream || !strm->substream->runtime) in rz_ssi_dma_complete()
653 rz_ssi_pointer_update(strm, strm->substream->runtime->period_size); in rz_ssi_dma_complete()
656 rz_ssi_dma_transfer(strm->priv, strm); in rz_ssi_dma_complete()
661 if (ssi->playback.dma_ch) { in rz_ssi_release_dma_channels()
662 dma_release_channel(ssi->playback.dma_ch); in rz_ssi_release_dma_channels()
663 ssi->playback.dma_ch = NULL; in rz_ssi_release_dma_channels()
664 if (ssi->dma_rt) in rz_ssi_release_dma_channels()
665 ssi->dma_rt = false; in rz_ssi_release_dma_channels()
668 if (ssi->capture.dma_ch) { in rz_ssi_release_dma_channels()
669 dma_release_channel(ssi->capture.dma_ch); in rz_ssi_release_dma_channels()
670 ssi->capture.dma_ch = NULL; in rz_ssi_release_dma_channels()
676 ssi->playback.dma_ch = dma_request_chan(dev, "tx"); in rz_ssi_dma_request()
677 if (IS_ERR(ssi->playback.dma_ch)) in rz_ssi_dma_request()
678 ssi->playback.dma_ch = NULL; in rz_ssi_dma_request()
680 ssi->capture.dma_ch = dma_request_chan(dev, "rx"); in rz_ssi_dma_request()
681 if (IS_ERR(ssi->capture.dma_ch)) in rz_ssi_dma_request()
682 ssi->capture.dma_ch = NULL; in rz_ssi_dma_request()
684 if (!ssi->playback.dma_ch && !ssi->capture.dma_ch) { in rz_ssi_dma_request()
685 ssi->playback.dma_ch = dma_request_chan(dev, "rt"); in rz_ssi_dma_request()
686 if (IS_ERR(ssi->playback.dma_ch)) { in rz_ssi_dma_request()
687 ssi->playback.dma_ch = NULL; in rz_ssi_dma_request()
691 ssi->dma_rt = true; in rz_ssi_dma_request()
697 if (ssi->playback.dma_ch && in rz_ssi_dma_request()
698 (rz_ssi_dma_slave_config(ssi, ssi->playback.dma_ch, true) < 0)) in rz_ssi_dma_request()
701 if (ssi->capture.dma_ch && in rz_ssi_dma_request()
702 (rz_ssi_dma_slave_config(ssi, ssi->capture.dma_ch, false) < 0)) in rz_ssi_dma_request()
710 return -ENODEV; in rz_ssi_dma_request()
729 if (ssi->dma_rt) { in rz_ssi_dai_trigger()
733 ret = rz_ssi_dma_slave_config(ssi, ssi->playback.dma_ch, in rz_ssi_dai_trigger()
737 ssi->playback.transfer = rz_ssi_pio_send; in rz_ssi_dai_trigger()
738 ssi->capture.transfer = rz_ssi_pio_recv; in rz_ssi_dai_trigger()
748 ret = strm->transfer(ssi, strm); in rz_ssi_dai_trigger()
773 dev_err(ssi->dev, "Codec should be clk and frame consumer\n"); in rz_ssi_dai_set_fmt()
774 return -EINVAL; in rz_ssi_dai_set_fmt()
785 ssi->bckp_rise = false; in rz_ssi_dai_set_fmt()
786 ssi->lrckp_fsync_fall = false; in rz_ssi_dai_set_fmt()
789 ssi->bckp_rise = false; in rz_ssi_dai_set_fmt()
790 ssi->lrckp_fsync_fall = true; in rz_ssi_dai_set_fmt()
793 ssi->bckp_rise = true; in rz_ssi_dai_set_fmt()
794 ssi->lrckp_fsync_fall = false; in rz_ssi_dai_set_fmt()
797 ssi->bckp_rise = true; in rz_ssi_dai_set_fmt()
798 ssi->lrckp_fsync_fall = true; in rz_ssi_dai_set_fmt()
801 return -EINVAL; in rz_ssi_dai_set_fmt()
809 dev_err(ssi->dev, "Only I2S mode is supported.\n"); in rz_ssi_dai_set_fmt()
810 return -EINVAL; in rz_ssi_dai_set_fmt()
822 SNDRV_PCM_HW_PARAM_SAMPLE_BITS)->min; in rz_ssi_dai_hw_params()
823 unsigned int channels = params_channels(params); in rz_ssi_dai_hw_params() local
826 dev_err(ssi->dev, "Unsupported sample width: %d\n", in rz_ssi_dai_hw_params()
828 return -EINVAL; in rz_ssi_dai_hw_params()
831 if (channels != 2) { in rz_ssi_dai_hw_params()
832 dev_err(ssi->dev, "Number of channels not matched: %d\n", in rz_ssi_dai_hw_params()
833 channels); in rz_ssi_dai_hw_params()
834 return -EINVAL; in rz_ssi_dai_hw_params()
866 return snd_pcm_hw_constraint_integer(substream->runtime, in rz_ssi_pcm_open()
877 return strm->buffer_pos; in rz_ssi_pcm_pointer()
883 snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, in rz_ssi_pcm_new()
884 rtd->card->snd_card->dev, in rz_ssi_pcm_new()
891 .name = "rz-ssi-dai",
898 .capture = {
909 .name = "rz-ssi",
923 ssi = devm_kzalloc(&pdev->dev, sizeof(*ssi), GFP_KERNEL); in rz_ssi_probe()
925 return -ENOMEM; in rz_ssi_probe()
927 ssi->pdev = pdev; in rz_ssi_probe()
928 ssi->dev = &pdev->dev; in rz_ssi_probe()
929 ssi->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); in rz_ssi_probe()
930 if (IS_ERR(ssi->base)) in rz_ssi_probe()
931 return PTR_ERR(ssi->base); in rz_ssi_probe()
933 ssi->phys = res->start; in rz_ssi_probe()
934 ssi->clk = devm_clk_get(&pdev->dev, "ssi"); in rz_ssi_probe()
935 if (IS_ERR(ssi->clk)) in rz_ssi_probe()
936 return PTR_ERR(ssi->clk); in rz_ssi_probe()
938 ssi->sfr_clk = devm_clk_get(&pdev->dev, "ssi_sfr"); in rz_ssi_probe()
939 if (IS_ERR(ssi->sfr_clk)) in rz_ssi_probe()
940 return PTR_ERR(ssi->sfr_clk); in rz_ssi_probe()
942 audio_clk = devm_clk_get(&pdev->dev, "audio_clk1"); in rz_ssi_probe()
944 return dev_err_probe(&pdev->dev, PTR_ERR(audio_clk), in rz_ssi_probe()
947 ssi->audio_clk_1 = clk_get_rate(audio_clk); in rz_ssi_probe()
948 audio_clk = devm_clk_get(&pdev->dev, "audio_clk2"); in rz_ssi_probe()
950 return dev_err_probe(&pdev->dev, PTR_ERR(audio_clk), in rz_ssi_probe()
953 ssi->audio_clk_2 = clk_get_rate(audio_clk); in rz_ssi_probe()
954 if (!(ssi->audio_clk_1 || ssi->audio_clk_2)) in rz_ssi_probe()
955 return dev_err_probe(&pdev->dev, -EINVAL, in rz_ssi_probe()
958 ssi->audio_mck = ssi->audio_clk_1 ? ssi->audio_clk_1 : ssi->audio_clk_2; in rz_ssi_probe()
961 ret = rz_ssi_dma_request(ssi, &pdev->dev); in rz_ssi_probe()
963 dev_warn(&pdev->dev, "DMA not available, using PIO\n"); in rz_ssi_probe()
964 ssi->playback.transfer = rz_ssi_pio_send; in rz_ssi_probe()
965 ssi->capture.transfer = rz_ssi_pio_recv; in rz_ssi_probe()
967 dev_info(&pdev->dev, "DMA enabled"); in rz_ssi_probe()
968 ssi->playback.transfer = rz_ssi_dma_transfer; in rz_ssi_probe()
969 ssi->capture.transfer = rz_ssi_dma_transfer; in rz_ssi_probe()
972 ssi->playback.priv = ssi; in rz_ssi_probe()
973 ssi->capture.priv = ssi; in rz_ssi_probe()
975 spin_lock_init(&ssi->lock); in rz_ssi_probe()
976 dev_set_drvdata(&pdev->dev, ssi); in rz_ssi_probe()
979 ssi->irq_int = platform_get_irq_byname(pdev, "int_req"); in rz_ssi_probe()
980 if (ssi->irq_int < 0) { in rz_ssi_probe()
982 return ssi->irq_int; in rz_ssi_probe()
985 ret = devm_request_irq(&pdev->dev, ssi->irq_int, &rz_ssi_interrupt, in rz_ssi_probe()
986 0, dev_name(&pdev->dev), ssi); in rz_ssi_probe()
989 return dev_err_probe(&pdev->dev, ret, in rz_ssi_probe()
995 ssi->irq_tx = platform_get_irq_byname(pdev, "dma_tx"); in rz_ssi_probe()
996 if (ssi->irq_tx < 0) in rz_ssi_probe()
997 return ssi->irq_tx; in rz_ssi_probe()
999 ret = devm_request_irq(&pdev->dev, ssi->irq_tx, in rz_ssi_probe()
1001 dev_name(&pdev->dev), ssi); in rz_ssi_probe()
1003 return dev_err_probe(&pdev->dev, ret, in rz_ssi_probe()
1006 ssi->irq_rx = platform_get_irq_byname(pdev, "dma_rx"); in rz_ssi_probe()
1007 if (ssi->irq_rx < 0) in rz_ssi_probe()
1008 return ssi->irq_rx; in rz_ssi_probe()
1010 ret = devm_request_irq(&pdev->dev, ssi->irq_rx, in rz_ssi_probe()
1012 dev_name(&pdev->dev), ssi); in rz_ssi_probe()
1014 return dev_err_probe(&pdev->dev, ret, in rz_ssi_probe()
1018 ssi->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL); in rz_ssi_probe()
1019 if (IS_ERR(ssi->rstc)) { in rz_ssi_probe()
1020 ret = PTR_ERR(ssi->rstc); in rz_ssi_probe()
1024 reset_control_deassert(ssi->rstc); in rz_ssi_probe()
1025 pm_runtime_enable(&pdev->dev); in rz_ssi_probe()
1026 ret = pm_runtime_resume_and_get(&pdev->dev); in rz_ssi_probe()
1028 dev_err(&pdev->dev, "pm_runtime_resume_and_get failed\n"); in rz_ssi_probe()
1032 ret = devm_snd_soc_register_component(&pdev->dev, &rz_ssi_soc_component, in rz_ssi_probe()
1036 dev_err(&pdev->dev, "failed to register snd component\n"); in rz_ssi_probe()
1043 pm_runtime_put(ssi->dev); in rz_ssi_probe()
1045 pm_runtime_disable(ssi->dev); in rz_ssi_probe()
1046 reset_control_assert(ssi->rstc); in rz_ssi_probe()
1055 struct rz_ssi_priv *ssi = dev_get_drvdata(&pdev->dev); in rz_ssi_remove()
1059 pm_runtime_put(ssi->dev); in rz_ssi_remove()
1060 pm_runtime_disable(ssi->dev); in rz_ssi_remove()
1061 reset_control_assert(ssi->rstc); in rz_ssi_remove()
1067 { .compatible = "renesas,rz-ssi", },
1074 .name = "rz-ssi-pcm-audio",