Lines Matching +full:capture +full:- +full:channels
1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
16 #include "sof-priv.h"
17 #include "sof-audio.h"
31 int stream = substream->stream; in create_page_table()
35 return -EINVAL; in create_page_table()
37 return snd_sof_create_page_table(component->dev, dmab, in create_page_table()
38 spcm->stream[stream].page_table.area, size); in create_page_table()
44 struct snd_soc_component *scomp = spcm->scomp; in sof_pcm_dsp_params()
51 dev_err(scomp->dev, "error: got wrong reply for PCM %d\n", in sof_pcm_dsp_params()
52 spcm->pcm.pcm_id); in sof_pcm_dsp_params()
66 snd_pcm_period_elapsed(sps->substream); in snd_sof_pcm_period_elapsed_work()
81 dev_err(component->dev, in snd_sof_pcm_period_elapsed()
94 schedule_work(&spcm->stream[substream->stream].period_elapsed_work); in snd_sof_pcm_period_elapsed()
108 stream.comp_id = spcm->stream[substream->stream].comp_id; in sof_pcm_dsp_pcm_free()
111 ret = sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream, in sof_pcm_dsp_pcm_free()
114 spcm->prepared[substream->stream] = false; in sof_pcm_dsp_pcm_free()
124 struct snd_pcm_runtime *runtime = substream->runtime; in sof_pcm_hw_params()
132 if (rtd->dai_link->no_pcm) in sof_pcm_hw_params()
137 return -EINVAL; in sof_pcm_hw_params()
143 if (spcm->prepared[substream->stream]) { in sof_pcm_hw_params()
149 dev_dbg(component->dev, "pcm: hw params stream %d dir %d\n", in sof_pcm_hw_params()
150 spcm->pcm.pcm_id, substream->stream); in sof_pcm_hw_params()
155 if (runtime->buffer_changed) { in sof_pcm_hw_params()
156 ret = create_page_table(component, substream, runtime->dma_area, in sof_pcm_hw_params()
157 runtime->dma_bytes); in sof_pcm_hw_params()
163 pcm.params.buffer.pages = PFN_UP(runtime->dma_bytes); in sof_pcm_hw_params()
168 pcm.comp_id = spcm->stream[substream->stream].comp_id; in sof_pcm_hw_params()
171 spcm->stream[substream->stream].page_table.addr; in sof_pcm_hw_params()
172 pcm.params.buffer.size = runtime->dma_bytes; in sof_pcm_hw_params()
173 pcm.params.direction = substream->stream; in sof_pcm_hw_params()
177 pcm.params.channels = params_channels(params); in sof_pcm_hw_params()
201 return -EINVAL; in sof_pcm_hw_params()
210 dev_err(component->dev, "error: platform hw params failed\n"); in sof_pcm_hw_params()
214 dev_dbg(component->dev, "stream_tag %d", pcm.params.stream_tag); in sof_pcm_hw_params()
217 ret = sof_ipc_tx_message(sdev->ipc, pcm.hdr.cmd, &pcm, sizeof(pcm), in sof_pcm_hw_params()
220 dev_err(component->dev, "error: hw params ipc failed for stream %d\n", in sof_pcm_hw_params()
229 spcm->prepared[substream->stream] = true; in sof_pcm_hw_params()
232 memcpy(&spcm->params[substream->stream], params, sizeof(*params)); in sof_pcm_hw_params()
246 if (rtd->dai_link->no_pcm) in sof_pcm_hw_free()
251 return -EINVAL; in sof_pcm_hw_free()
253 dev_dbg(component->dev, "pcm: free stream %d dir %d\n", in sof_pcm_hw_free()
254 spcm->pcm.pcm_id, substream->stream); in sof_pcm_hw_free()
256 if (spcm->prepared[substream->stream]) { in sof_pcm_hw_free()
262 cancel_work_sync(&spcm->stream[substream->stream].period_elapsed_work); in sof_pcm_hw_free()
266 dev_err(component->dev, "error: platform hw free failed\n"); in sof_pcm_hw_free()
281 if (rtd->dai_link->no_pcm) in sof_pcm_prepare()
286 return -EINVAL; in sof_pcm_prepare()
288 if (spcm->prepared[substream->stream]) in sof_pcm_prepare()
291 dev_dbg(component->dev, "pcm: prepare stream %d dir %d\n", in sof_pcm_prepare()
292 spcm->pcm.pcm_id, substream->stream); in sof_pcm_prepare()
296 substream, &spcm->params[substream->stream]); in sof_pcm_prepare()
298 dev_err(component->dev, in sof_pcm_prepare()
307 * FE dai link trigger actions are always executed in non-atomic context because
323 if (rtd->dai_link->no_pcm) in sof_pcm_trigger()
328 return -EINVAL; in sof_pcm_trigger()
330 dev_dbg(component->dev, "pcm: trigger stream %d dir %d cmd %d\n", in sof_pcm_trigger()
331 spcm->pcm.pcm_id, substream->stream, cmd); in sof_pcm_trigger()
335 stream.comp_id = spcm->stream[substream->stream].comp_id; in sof_pcm_trigger()
346 if (spcm->stream[substream->stream].suspend_ignored) { in sof_pcm_trigger()
352 spcm->stream[substream->stream].suspend_ignored = false; in sof_pcm_trigger()
359 dev_err(component->dev, in sof_pcm_trigger()
366 if (spcm->stream[substream->stream].suspend_ignored) { in sof_pcm_trigger()
369 * not supported, no need to re-start streams that in sof_pcm_trigger()
372 spcm->stream[substream->stream].suspend_ignored = false; in sof_pcm_trigger()
378 if (sdev->system_suspend_target == SOF_SUSPEND_S0IX && in sof_pcm_trigger()
379 spcm->stream[substream->stream].d0i3_compatible) { in sof_pcm_trigger()
386 spcm->stream[substream->stream].suspend_ignored = true; in sof_pcm_trigger()
396 dev_err(component->dev, "error: unhandled trigger cmd %d\n", in sof_pcm_trigger()
398 return -EINVAL; in sof_pcm_trigger()
409 ret = sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream, in sof_pcm_trigger()
432 if (rtd->dai_link->no_pcm) in sof_pcm_pointer()
436 if (sof_ops(sdev)->pcm_pointer) in sof_pcm_pointer()
437 return sof_ops(sdev)->pcm_pointer(sdev, substream); in sof_pcm_pointer()
441 return -EINVAL; in sof_pcm_pointer()
444 host = bytes_to_frames(substream->runtime, in sof_pcm_pointer()
445 spcm->stream[substream->stream].posn.host_posn); in sof_pcm_pointer()
446 dai = bytes_to_frames(substream->runtime, in sof_pcm_pointer()
447 spcm->stream[substream->stream].posn.dai_posn); in sof_pcm_pointer()
449 dev_vdbg(component->dev, in sof_pcm_pointer()
451 spcm->pcm.pcm_id, substream->stream, host, dai); in sof_pcm_pointer()
460 struct snd_pcm_runtime *runtime = substream->runtime; in sof_pcm_open()
468 if (rtd->dai_link->no_pcm) in sof_pcm_open()
473 return -EINVAL; in sof_pcm_open()
475 dev_dbg(component->dev, "pcm: open stream %d dir %d\n", in sof_pcm_open()
476 spcm->pcm.pcm_id, substream->stream); in sof_pcm_open()
479 caps = &spcm->pcm.caps[substream->stream]; in sof_pcm_open()
482 snd_pcm_hw_constraint_step(substream->runtime, 0, in sof_pcm_open()
484 le32_to_cpu(caps->period_size_min)); in sof_pcm_open()
485 snd_pcm_hw_constraint_step(substream->runtime, 0, in sof_pcm_open()
487 le32_to_cpu(caps->period_size_min)); in sof_pcm_open()
490 runtime->hw.info = ops->hw_info; /* platform-specific */ in sof_pcm_open()
492 runtime->hw.formats = le64_to_cpu(caps->formats); in sof_pcm_open()
493 runtime->hw.period_bytes_min = le32_to_cpu(caps->period_size_min); in sof_pcm_open()
494 runtime->hw.period_bytes_max = le32_to_cpu(caps->period_size_max); in sof_pcm_open()
495 runtime->hw.periods_min = le32_to_cpu(caps->periods_min); in sof_pcm_open()
496 runtime->hw.periods_max = le32_to_cpu(caps->periods_max); in sof_pcm_open()
499 * caps->buffer_size_min is not used since the in sof_pcm_open()
502 runtime->hw.buffer_bytes_max = le32_to_cpu(caps->buffer_size_max); in sof_pcm_open()
504 dev_dbg(component->dev, "period min %zd max %zd bytes\n", in sof_pcm_open()
505 runtime->hw.period_bytes_min, in sof_pcm_open()
506 runtime->hw.period_bytes_max); in sof_pcm_open()
507 dev_dbg(component->dev, "period count %d max %d\n", in sof_pcm_open()
508 runtime->hw.periods_min, in sof_pcm_open()
509 runtime->hw.periods_max); in sof_pcm_open()
510 dev_dbg(component->dev, "buffer max %zd bytes\n", in sof_pcm_open()
511 runtime->hw.buffer_bytes_max); in sof_pcm_open()
513 /* set wait time - TODO: come from topology */ in sof_pcm_open()
514 substream->wait_time = 500; in sof_pcm_open()
516 spcm->stream[substream->stream].posn.host_posn = 0; in sof_pcm_open()
517 spcm->stream[substream->stream].posn.dai_posn = 0; in sof_pcm_open()
518 spcm->stream[substream->stream].substream = substream; in sof_pcm_open()
519 spcm->prepared[substream->stream] = false; in sof_pcm_open()
523 dev_err(component->dev, "error: pcm open failed %d\n", ret); in sof_pcm_open()
537 if (rtd->dai_link->no_pcm) in sof_pcm_close()
542 return -EINVAL; in sof_pcm_close()
544 dev_dbg(component->dev, "pcm: close stream %d dir %d\n", in sof_pcm_close()
545 spcm->pcm.pcm_id, substream->stream); in sof_pcm_close()
549 dev_err(component->dev, "error: pcm close failed %d\n", in sof_pcm_close()
561 * Pre-allocate playback/capture audio buffer pages.
570 struct snd_pcm *pcm = rtd->pcm; in sof_pcm_new()
577 dev_warn(component->dev, "warn: can't find PCM with DAI ID %d\n", in sof_pcm_new()
578 rtd->dai_link->id); in sof_pcm_new()
582 dev_dbg(component->dev, "creating new PCM %s\n", spcm->pcm.pcm_name); in sof_pcm_new()
584 /* do we need to pre-allocate playback audio buffer pages */ in sof_pcm_new()
585 if (!spcm->pcm.playback) in sof_pcm_new()
586 goto capture; in sof_pcm_new()
588 caps = &spcm->pcm.caps[stream]; in sof_pcm_new()
590 /* pre-allocate playback audio buffer pages */ in sof_pcm_new()
591 dev_dbg(component->dev, in sof_pcm_new()
593 caps->name, caps->buffer_size_min, caps->buffer_size_max); in sof_pcm_new()
595 if (!pcm->streams[stream].substream) { in sof_pcm_new()
596 dev_err(component->dev, "error: NULL playback substream!\n"); in sof_pcm_new()
597 return -EINVAL; in sof_pcm_new()
600 snd_pcm_set_managed_buffer(pcm->streams[stream].substream, in sof_pcm_new()
601 SNDRV_DMA_TYPE_DEV_SG, sdev->dev, in sof_pcm_new()
602 0, le32_to_cpu(caps->buffer_size_max)); in sof_pcm_new()
603 capture: in sof_pcm_new()
606 /* do we need to pre-allocate capture audio buffer pages */ in sof_pcm_new()
607 if (!spcm->pcm.capture) in sof_pcm_new()
610 caps = &spcm->pcm.caps[stream]; in sof_pcm_new()
612 /* pre-allocate capture audio buffer pages */ in sof_pcm_new()
613 dev_dbg(component->dev, in sof_pcm_new()
614 "spcm: allocate %s capture DMA buffer size 0x%x max 0x%x\n", in sof_pcm_new()
615 caps->name, caps->buffer_size_min, caps->buffer_size_max); in sof_pcm_new()
617 if (!pcm->streams[stream].substream) { in sof_pcm_new()
618 dev_err(component->dev, "error: NULL capture substream!\n"); in sof_pcm_new()
619 return -EINVAL; in sof_pcm_new()
622 snd_pcm_set_managed_buffer(pcm->streams[stream].substream, in sof_pcm_new()
623 SNDRV_DMA_TYPE_DEV_SG, sdev->dev, in sof_pcm_new()
624 0, le32_to_cpu(caps->buffer_size_max)); in sof_pcm_new()
635 struct snd_interval *channels = hw_param_interval(params, in sof_pcm_dai_link_fixup() local
641 snd_sof_find_dai(component, (char *)rtd->dai_link->name); in sof_pcm_dai_link_fixup()
646 dev_warn(component->dev, in sof_pcm_dai_link_fixup()
648 rtd->dai_link->name); in sof_pcm_dai_link_fixup()
651 rate->min = 48000; in sof_pcm_dai_link_fixup()
652 rate->max = 48000; in sof_pcm_dai_link_fixup()
654 channels->min = 2; in sof_pcm_dai_link_fixup()
655 channels->max = 2; in sof_pcm_dai_link_fixup()
666 switch (dai->comp_dai.config.frame_fmt) { in sof_pcm_dai_link_fixup()
677 dev_err(component->dev, "error: No available DAI format!\n"); in sof_pcm_dai_link_fixup()
678 return -EINVAL; in sof_pcm_dai_link_fixup()
681 /* read rate and channels from topology */ in sof_pcm_dai_link_fixup()
682 switch (dai->dai_config->type) { in sof_pcm_dai_link_fixup()
684 rate->min = dai->dai_config->ssp.fsync_rate; in sof_pcm_dai_link_fixup()
685 rate->max = dai->dai_config->ssp.fsync_rate; in sof_pcm_dai_link_fixup()
686 channels->min = dai->dai_config->ssp.tdm_slots; in sof_pcm_dai_link_fixup()
687 channels->max = dai->dai_config->ssp.tdm_slots; in sof_pcm_dai_link_fixup()
689 dev_dbg(component->dev, in sof_pcm_dai_link_fixup()
690 "rate_min: %d rate_max: %d\n", rate->min, rate->max); in sof_pcm_dai_link_fixup()
691 dev_dbg(component->dev, in sof_pcm_dai_link_fixup()
693 channels->min, channels->max); in sof_pcm_dai_link_fixup()
698 if (dai->comp_dai.config.frame_fmt == SOF_IPC_FRAME_S24_4LE) { in sof_pcm_dai_link_fixup()
699 dev_err(component->dev, in sof_pcm_dai_link_fixup()
701 dai->comp_dai.config.frame_fmt, in sof_pcm_dai_link_fixup()
702 dai->dai_config->type); in sof_pcm_dai_link_fixup()
711 struct snd_soc_pcm_runtime *fe = dpcm->fe; in sof_pcm_dai_link_fixup()
713 fe->dai_link->trigger[SNDRV_PCM_STREAM_PLAYBACK] = in sof_pcm_dai_link_fixup()
721 rate->min = dai->dai_config->esai.fsync_rate; in sof_pcm_dai_link_fixup()
722 rate->max = dai->dai_config->esai.fsync_rate; in sof_pcm_dai_link_fixup()
723 channels->min = dai->dai_config->esai.tdm_slots; in sof_pcm_dai_link_fixup()
724 channels->max = dai->dai_config->esai.tdm_slots; in sof_pcm_dai_link_fixup()
726 dev_dbg(component->dev, in sof_pcm_dai_link_fixup()
727 "rate_min: %d rate_max: %d\n", rate->min, rate->max); in sof_pcm_dai_link_fixup()
728 dev_dbg(component->dev, in sof_pcm_dai_link_fixup()
730 channels->min, channels->max); in sof_pcm_dai_link_fixup()
733 rate->min = dai->dai_config->sai.fsync_rate; in sof_pcm_dai_link_fixup()
734 rate->max = dai->dai_config->sai.fsync_rate; in sof_pcm_dai_link_fixup()
735 channels->min = dai->dai_config->sai.tdm_slots; in sof_pcm_dai_link_fixup()
736 channels->max = dai->dai_config->sai.tdm_slots; in sof_pcm_dai_link_fixup()
738 dev_dbg(component->dev, in sof_pcm_dai_link_fixup()
739 "rate_min: %d rate_max: %d\n", rate->min, rate->max); in sof_pcm_dai_link_fixup()
740 dev_dbg(component->dev, in sof_pcm_dai_link_fixup()
742 channels->min, channels->max); in sof_pcm_dai_link_fixup()
745 dev_err(component->dev, "error: invalid DAI type %d\n", in sof_pcm_dai_link_fixup()
746 dai->dai_config->type); in sof_pcm_dai_link_fixup()
756 struct snd_sof_pdata *plat_data = sdev->pdata; in sof_pcm_probe()
761 sdev->component = component; in sof_pcm_probe()
763 tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL, in sof_pcm_probe()
765 plat_data->tplg_filename_prefix, in sof_pcm_probe()
766 plat_data->tplg_filename); in sof_pcm_probe()
768 return -ENOMEM; in sof_pcm_probe()
772 dev_err(component->dev, "error: failed to load DSP topology %d\n", in sof_pcm_probe()
788 struct snd_soc_component_driver *pd = &sdev->plat_drv; in snd_sof_new_platform_drv()
789 struct snd_sof_pdata *plat_data = sdev->pdata; in snd_sof_new_platform_drv()
792 drv_name = plat_data->machine->drv_name; in snd_sof_new_platform_drv()
794 pd->name = "sof-audio-component"; in snd_sof_new_platform_drv()
795 pd->probe = sof_pcm_probe; in snd_sof_new_platform_drv()
796 pd->remove = sof_pcm_remove; in snd_sof_new_platform_drv()
797 pd->open = sof_pcm_open; in snd_sof_new_platform_drv()
798 pd->close = sof_pcm_close; in snd_sof_new_platform_drv()
799 pd->hw_params = sof_pcm_hw_params; in snd_sof_new_platform_drv()
800 pd->prepare = sof_pcm_prepare; in snd_sof_new_platform_drv()
801 pd->hw_free = sof_pcm_hw_free; in snd_sof_new_platform_drv()
802 pd->trigger = sof_pcm_trigger; in snd_sof_new_platform_drv()
803 pd->pointer = sof_pcm_pointer; in snd_sof_new_platform_drv()
806 pd->compress_ops = &sof_compressed_ops; in snd_sof_new_platform_drv()
810 pd->compress_ops = &sof_probe_compressed_ops; in snd_sof_new_platform_drv()
812 pd->pcm_construct = sof_pcm_new; in snd_sof_new_platform_drv()
813 pd->ignore_machine = drv_name; in snd_sof_new_platform_drv()
814 pd->be_hw_params_fixup = sof_pcm_dai_link_fixup; in snd_sof_new_platform_drv()
815 pd->be_pcm_base = SOF_BE_PCM_BASE; in snd_sof_new_platform_drv()
816 pd->use_dai_pcm_id = true; in snd_sof_new_platform_drv()
817 pd->topology_name_prefix = "sof"; in snd_sof_new_platform_drv()
820 pd->module_get_upon_open = 1; in snd_sof_new_platform_drv()