Lines Matching +full:dsp +full:- +full:config +full:- +full:name
1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
17 #include "sof-of-dev.h"
18 #include "sof-priv.h"
19 #include "sof-audio.h"
20 #include "sof-utils.h"
23 /* Create DMA buffer page table for DSP */
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()
50 snd_pcm_period_elapsed(sps->substream); in snd_sof_pcm_period_elapsed_work()
70 dev_err(component->dev, in snd_sof_pcm_period_elapsed()
83 schedule_work(&spcm->stream[substream->stream].period_elapsed_work); in snd_sof_pcm_period_elapsed()
102 dev_err(sdev->dev, "error: dai %s has no valid %s path\n", dai->name, in sof_pcm_setup_connected_widgets()
107 spcm->stream[dir].list = list; in sof_pcm_setup_connected_widgets()
111 dev_err(sdev->dev, "error: failed widget list set up for pcm %d dir %d\n", in sof_pcm_setup_connected_widgets()
112 spcm->pcm.pcm_id, dir); in sof_pcm_setup_connected_widgets()
113 spcm->stream[dir].list = NULL; in sof_pcm_setup_connected_widgets()
130 struct snd_pcm_runtime *runtime = substream->runtime; in sof_pcm_hw_params()
135 if (rtd->dai_link->no_pcm) in sof_pcm_hw_params()
140 return -EINVAL; in sof_pcm_hw_params()
146 if (pcm_ops && pcm_ops->hw_free && spcm->prepared[substream->stream]) { in sof_pcm_hw_params()
147 ret = pcm_ops->hw_free(component, substream); in sof_pcm_hw_params()
151 spcm->prepared[substream->stream] = false; in sof_pcm_hw_params()
154 dev_dbg(component->dev, "pcm: hw params stream %d dir %d\n", in sof_pcm_hw_params()
155 spcm->pcm.pcm_id, substream->stream); in sof_pcm_hw_params()
159 dev_err(component->dev, "platform hw params failed\n"); in sof_pcm_hw_params()
164 if (!spcm->stream[substream->stream].list) { in sof_pcm_hw_params()
166 substream->stream); in sof_pcm_hw_params()
172 if (runtime->buffer_changed) { in sof_pcm_hw_params()
173 ret = create_page_table(component, substream, runtime->dma_area, in sof_pcm_hw_params()
174 runtime->dma_bytes); in sof_pcm_hw_params()
180 if (pcm_ops && pcm_ops->hw_params) { in sof_pcm_hw_params()
181 ret = pcm_ops->hw_params(component, substream, params, &platform_params); in sof_pcm_hw_params()
186 spcm->prepared[substream->stream] = true; in sof_pcm_hw_params()
189 memcpy(&spcm->params[substream->stream], params, sizeof(*params)); in sof_pcm_hw_params()
204 if (rtd->dai_link->no_pcm) in sof_pcm_hw_free()
209 return -EINVAL; in sof_pcm_hw_free()
211 dev_dbg(component->dev, "pcm: free stream %d dir %d\n", in sof_pcm_hw_free()
212 spcm->pcm.pcm_id, substream->stream); in sof_pcm_hw_free()
214 if (spcm->prepared[substream->stream]) { in sof_pcm_hw_free()
216 if (pcm_ops && pcm_ops->platform_stop_during_hw_free) in sof_pcm_hw_free()
219 /* free PCM in the DSP */ in sof_pcm_hw_free()
220 if (pcm_ops && pcm_ops->hw_free) { in sof_pcm_hw_free()
221 ret = pcm_ops->hw_free(component, substream); in sof_pcm_hw_free()
226 spcm->prepared[substream->stream] = false; in sof_pcm_hw_free()
232 dev_err(component->dev, "error: platform hw free failed\n"); in sof_pcm_hw_free()
237 ret = sof_widget_list_free(sdev, spcm, substream->stream); in sof_pcm_hw_free()
241 cancel_work_sync(&spcm->stream[substream->stream].period_elapsed_work); in sof_pcm_hw_free()
254 if (rtd->dai_link->no_pcm) in sof_pcm_prepare()
259 return -EINVAL; in sof_pcm_prepare()
261 if (spcm->prepared[substream->stream]) in sof_pcm_prepare()
264 dev_dbg(component->dev, "pcm: prepare stream %d dir %d\n", in sof_pcm_prepare()
265 spcm->pcm.pcm_id, substream->stream); in sof_pcm_prepare()
269 substream, &spcm->params[substream->stream]); in sof_pcm_prepare()
271 dev_err(component->dev, in sof_pcm_prepare()
280 * FE dai link trigger actions are always executed in non-atomic context because
295 if (rtd->dai_link->no_pcm) in sof_pcm_trigger()
300 return -EINVAL; in sof_pcm_trigger()
302 dev_dbg(component->dev, "pcm: trigger stream %d dir %d cmd %d\n", in sof_pcm_trigger()
303 spcm->pcm.pcm_id, substream->stream, cmd); in sof_pcm_trigger()
310 if (pcm_ops && pcm_ops->ipc_first_on_start) in sof_pcm_trigger()
314 if (spcm->stream[substream->stream].suspend_ignored) { in sof_pcm_trigger()
317 * not supported, no need to re-start streams that in sof_pcm_trigger()
320 spcm->stream[substream->stream].suspend_ignored = false; in sof_pcm_trigger()
324 if (pcm_ops && pcm_ops->ipc_first_on_start) in sof_pcm_trigger()
329 * If DSP D0I3 is allowed during S0iX, set the suspend_ignored flag for in sof_pcm_trigger()
330 * D0I3-compatible streams to keep the firmware pipeline running in sof_pcm_trigger()
332 if (pcm_ops && pcm_ops->d0i3_supported_in_s0ix && in sof_pcm_trigger()
333 sdev->system_suspend_target == SOF_SUSPEND_S0IX && in sof_pcm_trigger()
334 spcm->stream[substream->stream].d0i3_compatible) { in sof_pcm_trigger()
335 spcm->stream[substream->stream].suspend_ignored = true; in sof_pcm_trigger()
340 if (sdev->dspless_mode_selected) in sof_pcm_trigger()
346 if (pcm_ops && pcm_ops->reset_hw_params_during_stop) in sof_pcm_trigger()
350 dev_err(component->dev, "Unhandled trigger cmd %d\n", cmd); in sof_pcm_trigger()
351 return -EINVAL; in sof_pcm_trigger()
357 if (pcm_ops && pcm_ops->trigger) in sof_pcm_trigger()
358 ret = pcm_ops->trigger(component, substream, cmd); in sof_pcm_trigger()
371 if (!pcm_ops || !pcm_ops->platform_stop_during_hw_free) in sof_pcm_trigger()
380 ret = sof_pcm_stream_free(sdev, substream, spcm, substream->stream, false); in sof_pcm_trigger()
394 if (rtd->dai_link->no_pcm) in sof_pcm_pointer()
397 /* use dsp ops pointer callback directly if set */ in sof_pcm_pointer()
398 if (sof_ops(sdev)->pcm_pointer) in sof_pcm_pointer()
399 return sof_ops(sdev)->pcm_pointer(sdev, substream); in sof_pcm_pointer()
403 return -EINVAL; in sof_pcm_pointer()
405 /* read position from DSP */ in sof_pcm_pointer()
406 host = bytes_to_frames(substream->runtime, in sof_pcm_pointer()
407 spcm->stream[substream->stream].posn.host_posn); in sof_pcm_pointer()
408 dai = bytes_to_frames(substream->runtime, in sof_pcm_pointer()
409 spcm->stream[substream->stream].posn.dai_posn); in sof_pcm_pointer()
420 struct snd_pcm_runtime *runtime = substream->runtime; in sof_pcm_open()
428 if (rtd->dai_link->no_pcm) in sof_pcm_open()
433 return -EINVAL; in sof_pcm_open()
435 dev_dbg(component->dev, "pcm: open stream %d dir %d\n", in sof_pcm_open()
436 spcm->pcm.pcm_id, substream->stream); in sof_pcm_open()
439 caps = &spcm->pcm.caps[substream->stream]; in sof_pcm_open()
441 /* set runtime config */ in sof_pcm_open()
442 runtime->hw.info = ops->hw_info; /* platform-specific */ in sof_pcm_open()
445 runtime->hw.formats = le64_to_cpu(caps->formats); in sof_pcm_open()
446 runtime->hw.period_bytes_min = le32_to_cpu(caps->period_size_min); in sof_pcm_open()
447 runtime->hw.period_bytes_max = le32_to_cpu(caps->period_size_max); in sof_pcm_open()
448 runtime->hw.periods_min = le32_to_cpu(caps->periods_min); in sof_pcm_open()
449 runtime->hw.periods_max = le32_to_cpu(caps->periods_max); in sof_pcm_open()
452 * caps->buffer_size_min is not used since the in sof_pcm_open()
455 runtime->hw.buffer_bytes_max = le32_to_cpu(caps->buffer_size_max); in sof_pcm_open()
457 dev_dbg(component->dev, "period min %zd max %zd bytes\n", in sof_pcm_open()
458 runtime->hw.period_bytes_min, in sof_pcm_open()
459 runtime->hw.period_bytes_max); in sof_pcm_open()
460 dev_dbg(component->dev, "period count %d max %d\n", in sof_pcm_open()
461 runtime->hw.periods_min, in sof_pcm_open()
462 runtime->hw.periods_max); in sof_pcm_open()
463 dev_dbg(component->dev, "buffer max %zd bytes\n", in sof_pcm_open()
464 runtime->hw.buffer_bytes_max); in sof_pcm_open()
466 /* set wait time - TODO: come from topology */ in sof_pcm_open()
467 substream->wait_time = 500; in sof_pcm_open()
469 spcm->stream[substream->stream].posn.host_posn = 0; in sof_pcm_open()
470 spcm->stream[substream->stream].posn.dai_posn = 0; in sof_pcm_open()
471 spcm->stream[substream->stream].substream = substream; in sof_pcm_open()
472 spcm->prepared[substream->stream] = false; in sof_pcm_open()
476 dev_err(component->dev, "error: pcm open failed %d\n", ret); in sof_pcm_open()
490 if (rtd->dai_link->no_pcm) in sof_pcm_close()
495 return -EINVAL; in sof_pcm_close()
497 dev_dbg(component->dev, "pcm: close stream %d dir %d\n", in sof_pcm_close()
498 spcm->pcm.pcm_id, substream->stream); in sof_pcm_close()
502 dev_err(component->dev, "error: pcm close failed %d\n", in sof_pcm_close()
514 * Pre-allocate playback/capture audio buffer pages.
523 struct snd_pcm *pcm = rtd->pcm; in sof_pcm_new()
530 dev_warn(component->dev, "warn: can't find PCM with DAI ID %d\n", in sof_pcm_new()
531 rtd->dai_link->id); in sof_pcm_new()
535 dev_dbg(component->dev, "creating new PCM %s\n", spcm->pcm.pcm_name); in sof_pcm_new()
537 /* do we need to pre-allocate playback audio buffer pages */ in sof_pcm_new()
538 if (!spcm->pcm.playback) in sof_pcm_new()
541 caps = &spcm->pcm.caps[stream]; in sof_pcm_new()
543 /* pre-allocate playback audio buffer pages */ in sof_pcm_new()
544 dev_dbg(component->dev, in sof_pcm_new()
546 caps->name, caps->buffer_size_min, caps->buffer_size_max); in sof_pcm_new()
548 if (!pcm->streams[stream].substream) { in sof_pcm_new()
549 dev_err(component->dev, "error: NULL playback substream!\n"); in sof_pcm_new()
550 return -EINVAL; in sof_pcm_new()
553 snd_pcm_set_managed_buffer(pcm->streams[stream].substream, in sof_pcm_new()
554 SNDRV_DMA_TYPE_DEV_SG, sdev->dev, in sof_pcm_new()
555 0, le32_to_cpu(caps->buffer_size_max)); in sof_pcm_new()
559 /* do we need to pre-allocate capture audio buffer pages */ in sof_pcm_new()
560 if (!spcm->pcm.capture) in sof_pcm_new()
563 caps = &spcm->pcm.caps[stream]; in sof_pcm_new()
565 /* pre-allocate capture audio buffer pages */ in sof_pcm_new()
566 dev_dbg(component->dev, in sof_pcm_new()
568 caps->name, caps->buffer_size_min, caps->buffer_size_max); in sof_pcm_new()
570 if (!pcm->streams[stream].substream) { in sof_pcm_new()
571 dev_err(component->dev, "error: NULL capture substream!\n"); in sof_pcm_new()
572 return -EINVAL; in sof_pcm_new()
575 snd_pcm_set_managed_buffer(pcm->streams[stream].substream, in sof_pcm_new()
576 SNDRV_DMA_TYPE_DEV_SG, sdev->dev, in sof_pcm_new()
577 0, le32_to_cpu(caps->buffer_size_max)); in sof_pcm_new()
593 snd_sof_find_dai(component, (char *)rtd->dai_link->name); in sof_pcm_dai_link_fixup()
599 dev_warn(component->dev, in sof_pcm_dai_link_fixup()
600 "warning: no topology found for BE DAI %s config\n", in sof_pcm_dai_link_fixup()
601 rtd->dai_link->name); in sof_pcm_dai_link_fixup()
604 rate->min = 48000; in sof_pcm_dai_link_fixup()
605 rate->max = 48000; in sof_pcm_dai_link_fixup()
607 channels->min = 2; in sof_pcm_dai_link_fixup()
608 channels->max = 2; in sof_pcm_dai_link_fixup()
616 if (pcm_ops && pcm_ops->dai_link_fixup) in sof_pcm_dai_link_fixup()
617 return pcm_ops->dai_link_fixup(rtd, params); in sof_pcm_dai_link_fixup()
626 struct snd_sof_pdata *plat_data = sdev->pdata; in sof_pcm_probe()
634 ret = pm_runtime_resume_and_get(component->dev); in sof_pcm_probe()
635 if (ret < 0 && ret != -EACCES) in sof_pcm_probe()
639 sdev->component = component; in sof_pcm_probe()
641 tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL, in sof_pcm_probe()
643 plat_data->tplg_filename_prefix, in sof_pcm_probe()
644 plat_data->tplg_filename); in sof_pcm_probe()
646 ret = -ENOMEM; in sof_pcm_probe()
652 dev_err(component->dev, "error: failed to load DSP topology %d\n", in sof_pcm_probe()
656 pm_runtime_mark_last_busy(component->dev); in sof_pcm_probe()
657 pm_runtime_put_autosuspend(component->dev); in sof_pcm_probe()
682 if (pcm_ops && pcm_ops->delay) in sof_pcm_delay()
683 return pcm_ops->delay(component, substream); in sof_pcm_delay()
690 struct snd_soc_component_driver *pd = &sdev->plat_drv; in snd_sof_new_platform_drv()
691 struct snd_sof_pdata *plat_data = sdev->pdata; in snd_sof_new_platform_drv()
694 if (plat_data->machine) in snd_sof_new_platform_drv()
695 drv_name = plat_data->machine->drv_name; in snd_sof_new_platform_drv()
696 else if (plat_data->of_machine) in snd_sof_new_platform_drv()
697 drv_name = plat_data->of_machine->drv_name; in snd_sof_new_platform_drv()
701 pd->name = "sof-audio-component"; in snd_sof_new_platform_drv()
702 pd->probe = sof_pcm_probe; in snd_sof_new_platform_drv()
703 pd->remove = sof_pcm_remove; in snd_sof_new_platform_drv()
704 pd->open = sof_pcm_open; in snd_sof_new_platform_drv()
705 pd->close = sof_pcm_close; in snd_sof_new_platform_drv()
706 pd->hw_params = sof_pcm_hw_params; in snd_sof_new_platform_drv()
707 pd->prepare = sof_pcm_prepare; in snd_sof_new_platform_drv()
708 pd->hw_free = sof_pcm_hw_free; in snd_sof_new_platform_drv()
709 pd->trigger = sof_pcm_trigger; in snd_sof_new_platform_drv()
710 pd->pointer = sof_pcm_pointer; in snd_sof_new_platform_drv()
711 pd->ack = sof_pcm_ack; in snd_sof_new_platform_drv()
712 pd->delay = sof_pcm_delay; in snd_sof_new_platform_drv()
715 pd->compress_ops = &sof_compressed_ops; in snd_sof_new_platform_drv()
718 pd->pcm_construct = sof_pcm_new; in snd_sof_new_platform_drv()
719 pd->ignore_machine = drv_name; in snd_sof_new_platform_drv()
720 pd->be_pcm_base = SOF_BE_PCM_BASE; in snd_sof_new_platform_drv()
721 pd->use_dai_pcm_id = true; in snd_sof_new_platform_drv()
722 pd->topology_name_prefix = "sof"; in snd_sof_new_platform_drv()
725 pd->module_get_upon_open = 1; in snd_sof_new_platform_drv()
727 pd->legacy_dai_naming = 1; in snd_sof_new_platform_drv()
730 * The fixup is only needed when the DSP is in use as with the DSPless in snd_sof_new_platform_drv()
733 if (!sdev->dspless_mode_selected) in snd_sof_new_platform_drv()
734 pd->be_hw_params_fixup = sof_pcm_dai_link_fixup; in snd_sof_new_platform_drv()