Lines Matching +full:fe +full:- +full:dai +full:- +full:link

1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
11 #include "sof-audio.h"
12 #include "sof-priv.h"
14 #include "ipc4-priv.h"
15 #include "ipc4-topology.h"
16 #include "ipc4-fw-reg.h"
19 * struct sof_ipc4_timestamp_info - IPC4 timestamp info
21 * @dai_copier: the dai copier of the pcm stream
41 * struct sof_ipc4_pcm_stream_priv - IPC4 specific private data
54 struct sof_ipc4_pcm_stream_priv *stream_priv = sps->private; in sof_ipc4_sps_to_time_info()
56 return stream_priv->time_info; in sof_ipc4_sps_to_time_info()
66 if (trigger_list->count == 1) in sof_ipc4_set_multi_pipeline_state()
67 return sof_ipc4_set_pipeline_state(sdev, trigger_list->pipeline_instance_ids[0], in sof_ipc4_set_multi_pipeline_state()
80 ipc_size = sizeof(u32) * (trigger_list->count + 1); in sof_ipc4_set_multi_pipeline_state()
84 return sof_ipc_tx_message_no_reply(sdev->ipc, &msg, ipc_size); in sof_ipc4_set_multi_pipeline_state()
92 dev_dbg(sdev->dev, "ipc4 set pipeline instance %d state %d", instance_id, state); in sof_ipc4_set_pipeline_state()
102 return sof_ipc_tx_message_no_reply(sdev->ipc, &msg, 0); in sof_ipc4_set_pipeline_state()
110 struct sof_ipc4_pipeline *pipeline = pipe_widget->private; in sof_ipc4_add_pipeline_by_priority()
113 for (i = 0; i < trigger_list->count; i++) { in sof_ipc4_add_pipeline_by_priority()
115 if (ascend && pipeline->priority < pipe_priority[i]) in sof_ipc4_add_pipeline_by_priority()
118 else if (!ascend && pipeline->priority > pipe_priority[i]) in sof_ipc4_add_pipeline_by_priority()
122 for (j = trigger_list->count - 1; j >= i; j--) { in sof_ipc4_add_pipeline_by_priority()
123 trigger_list->pipeline_instance_ids[j + 1] = trigger_list->pipeline_instance_ids[j]; in sof_ipc4_add_pipeline_by_priority()
127 trigger_list->pipeline_instance_ids[i] = pipe_widget->instance_id; in sof_ipc4_add_pipeline_by_priority()
128 trigger_list->count++; in sof_ipc4_add_pipeline_by_priority()
129 pipe_priority[i] = pipeline->priority; in sof_ipc4_add_pipeline_by_priority()
138 struct snd_sof_widget *pipe_widget = spipe->pipe_widget; in sof_ipc4_add_pipeline_to_trigger_list()
139 struct sof_ipc4_pipeline *pipeline = pipe_widget->private; in sof_ipc4_add_pipeline_to_trigger_list()
141 if (pipeline->skip_during_fe_trigger && state != SOF_IPC4_PIPE_RESET) in sof_ipc4_add_pipeline_to_trigger_list()
150 if (spipe->started_count == spipe->paused_count) in sof_ipc4_add_pipeline_to_trigger_list()
156 if (!spipe->started_count && !spipe->paused_count) in sof_ipc4_add_pipeline_to_trigger_list()
162 if (spipe->paused_count == (spipe->started_count - 1)) in sof_ipc4_add_pipeline_to_trigger_list()
176 struct snd_sof_widget *pipe_widget = spipe->pipe_widget; in sof_ipc4_update_pipeline_state()
177 struct sof_ipc4_pipeline *pipeline = pipe_widget->private; in sof_ipc4_update_pipeline_state()
180 if (pipeline->skip_during_fe_trigger && state != SOF_IPC4_PIPE_RESET) in sof_ipc4_update_pipeline_state()
184 for (i = 0; i < trigger_list->count; i++) { in sof_ipc4_update_pipeline_state()
185 if (trigger_list->pipeline_instance_ids[i] == pipe_widget->instance_id) { in sof_ipc4_update_pipeline_state()
186 pipeline->state = state; in sof_ipc4_update_pipeline_state()
199 spipe->paused_count++; in sof_ipc4_update_pipeline_state()
207 spipe->started_count--; in sof_ipc4_update_pipeline_state()
217 spipe->paused_count--; in sof_ipc4_update_pipeline_state()
222 spipe->started_count++; in sof_ipc4_update_pipeline_state()
236 * +---------------+
240 * +-------+-------+
246 * +----------------+ +------v-------+ +-------------+
248 * | RUNNING <-------------+ PAUSED +--------------> + RESET |
250 * +------+---------+ RELEASE +---------+----+ +-------------+
256 * +---------------------------------+
268 * buffer on DSP and directly from there to link DMA. However, the
269 * model on SOF driver has two notional pipelines, one at host DAI,
270 * and another at link DAI. They both shall have the use_chain_dma
279 struct sof_ipc4_fw_data *ipc4_data = sdev->private; in sof_ipc4_chain_dma_trigger()
285 stream_priv = spcm->stream[direction].private; in sof_ipc4_chain_dma_trigger()
308 if (!stream_priv->chain_dma_allocated) in sof_ipc4_chain_dma_trigger()
316 dev_err(sdev->dev, "Unexpected state %d", state); in sof_ipc4_chain_dma_trigger()
317 return -EINVAL; in sof_ipc4_chain_dma_trigger()
325 * To set-up the DMA chain, the host DMA ID and SCS setting in sof_ipc4_chain_dma_trigger()
327 * the link DMA ID and fifo_size are retrieved from the link in sof_ipc4_chain_dma_trigger()
330 for (i = 0; i < pipeline_list->count; i++) { in sof_ipc4_chain_dma_trigger()
331 struct snd_sof_pipeline *spipe = pipeline_list->pipelines[i]; in sof_ipc4_chain_dma_trigger()
332 struct snd_sof_widget *pipe_widget = spipe->pipe_widget; in sof_ipc4_chain_dma_trigger()
333 struct sof_ipc4_pipeline *pipeline = pipe_widget->private; in sof_ipc4_chain_dma_trigger()
335 if (!pipeline->use_chain_dma) { in sof_ipc4_chain_dma_trigger()
336 dev_err(sdev->dev, in sof_ipc4_chain_dma_trigger()
338 return -EINVAL; in sof_ipc4_chain_dma_trigger()
341 msg.primary |= pipeline->msg.primary; in sof_ipc4_chain_dma_trigger()
345 msg.extension |= pipeline->msg.extension; in sof_ipc4_chain_dma_trigger()
351 * playback: 0 - (num_playback_streams - 1) in sof_ipc4_chain_dma_trigger()
352 * capture: num_playback_streams - (num_playback_streams + in sof_ipc4_chain_dma_trigger()
353 * num_capture_streams - 1) in sof_ipc4_chain_dma_trigger()
358 msg.primary += SOF_IPC4_GLB_CHAIN_DMA_HOST_ID(ipc4_data->num_playback_streams); in sof_ipc4_chain_dma_trigger()
359 msg.primary += SOF_IPC4_GLB_CHAIN_DMA_LINK_ID(ipc4_data->num_playback_streams); in sof_ipc4_chain_dma_trigger()
368 ret = sof_ipc_tx_message_no_reply(sdev->ipc, &msg, 0); in sof_ipc4_chain_dma_trigger()
371 stream_priv->chain_dma_allocated = allocate; in sof_ipc4_chain_dma_trigger()
382 struct sof_ipc4_fw_data *ipc4_data = sdev->private; in sof_ipc4_trigger_pipelines()
392 dev_dbg(sdev->dev, "trigger cmd: %d state: %d\n", cmd, state); in sof_ipc4_trigger_pipelines()
396 return -EINVAL; in sof_ipc4_trigger_pipelines()
398 pipeline_list = &spcm->stream[substream->stream].pipeline_list; in sof_ipc4_trigger_pipelines()
401 if (!pipeline_list->pipelines || !pipeline_list->count) in sof_ipc4_trigger_pipelines()
404 spipe = pipeline_list->pipelines[0]; in sof_ipc4_trigger_pipelines()
405 pipe_widget = spipe->pipe_widget; in sof_ipc4_trigger_pipelines()
406 pipeline = pipe_widget->private; in sof_ipc4_trigger_pipelines()
412 if (pipeline->use_chain_dma) in sof_ipc4_trigger_pipelines()
413 return sof_ipc4_chain_dma_trigger(sdev, spcm, substream->stream, in sof_ipc4_trigger_pipelines()
418 pipeline_list->count), GFP_KERNEL); in sof_ipc4_trigger_pipelines()
420 return -ENOMEM; in sof_ipc4_trigger_pipelines()
422 pipe_priority = kzalloc(pipeline_list->count, GFP_KERNEL); in sof_ipc4_trigger_pipelines()
425 return -ENOMEM; in sof_ipc4_trigger_pipelines()
428 mutex_lock(&ipc4_data->pipeline_state_mutex); in sof_ipc4_trigger_pipelines()
433 * sink->source when starting PCM's and in the reverse order to pause/stop PCM's. in sof_ipc4_trigger_pipelines()
436 * indeterministic. But the sink->source trigger order sink->source would still be in sof_ipc4_trigger_pipelines()
440 for (i = pipeline_list->count - 1; i >= 0; i--) { in sof_ipc4_trigger_pipelines()
441 spipe = pipeline_list->pipelines[i]; in sof_ipc4_trigger_pipelines()
446 for (i = 0; i < pipeline_list->count; i++) { in sof_ipc4_trigger_pipelines()
447 spipe = pipeline_list->pipelines[i]; in sof_ipc4_trigger_pipelines()
453 if (!trigger_list->count) { in sof_ipc4_trigger_pipelines()
468 dev_err(sdev->dev, "failed to pause all pipelines\n"); in sof_ipc4_trigger_pipelines()
473 for (i = 0; i < pipeline_list->count ; i++) { in sof_ipc4_trigger_pipelines()
474 spipe = pipeline_list->pipelines[i]; in sof_ipc4_trigger_pipelines()
487 time_info = sof_ipc4_sps_to_time_info(&spcm->stream[substream->stream]); in sof_ipc4_trigger_pipelines()
489 time_info->stream_start_offset = SOF_IPC4_INVALID_STREAM_POSITION; in sof_ipc4_trigger_pipelines()
497 dev_err(sdev->dev, "failed to set final state %d for all pipelines\n", state); in sof_ipc4_trigger_pipelines()
506 if (sdev->fw_state != SOF_FW_CRASHED || state != SOF_IPC4_PIPE_RESET) in sof_ipc4_trigger_pipelines()
513 for (i = 0; i < pipeline_list->count; i++) { in sof_ipc4_trigger_pipelines()
514 spipe = pipeline_list->pipelines[i]; in sof_ipc4_trigger_pipelines()
519 mutex_unlock(&ipc4_data->pipeline_state_mutex); in sof_ipc4_trigger_pipelines()
543 dev_err(component->dev, "%s: unhandled trigger cmd %d\n", __func__, cmd); in sof_ipc4_pcm_trigger()
544 return -EINVAL; in sof_ipc4_pcm_trigger()
562 struct snd_sof_dai *dai; in ipc4_ssp_dai_config_pcm_params_match() local
566 list_for_each_entry(slink, &sdev->dai_link_list, list) { in ipc4_ssp_dai_config_pcm_params_match()
567 if (!strcmp(slink->link->name, link_name)) { in ipc4_ssp_dai_config_pcm_params_match()
576 for (i = 0; i < slink->num_hw_configs; i++) { in ipc4_ssp_dai_config_pcm_params_match()
577 struct snd_soc_tplg_hw_config *hw_config = &slink->hw_configs[i]; in ipc4_ssp_dai_config_pcm_params_match()
579 if (params_rate(params) == le32_to_cpu(hw_config->fsync_rate)) { in ipc4_ssp_dai_config_pcm_params_match()
580 /* set current config for all DAI's with matching name */ in ipc4_ssp_dai_config_pcm_params_match()
581 list_for_each_entry(dai, &sdev->dai_list, list) in ipc4_ssp_dai_config_pcm_params_match()
582 if (!strcmp(slink->link->name, dai->name)) in ipc4_ssp_dai_config_pcm_params_match()
583 dai->current_config = le32_to_cpu(hw_config->id); in ipc4_ssp_dai_config_pcm_params_match()
590 * Fixup DAI link parameters for sampling rate based on
591 * DAI copier configuration.
597 struct sof_ipc4_pin_format *pin_fmts = ipc4_copier->available_fmt.input_pin_fmts; in sof_ipc4_pcm_dai_link_fixup_rate()
599 int num_input_formats = ipc4_copier->available_fmt.num_input_formats; in sof_ipc4_pcm_dai_link_fixup_rate()
625 * If rate is different than FE rate, topology must in sof_ipc4_pcm_dai_link_fixup_rate()
627 * define a single rate in the DAI copier config in in sof_ipc4_pcm_dai_link_fixup_rate()
628 * this case (FE rate may be variable). in sof_ipc4_pcm_dai_link_fixup_rate()
632 dev_err(sdev->dev, "Unable to select sampling rate for DAI link\n"); in sof_ipc4_pcm_dai_link_fixup_rate()
633 return -EINVAL; in sof_ipc4_pcm_dai_link_fixup_rate()
636 rate->min = be_rate; in sof_ipc4_pcm_dai_link_fixup_rate()
637 rate->max = rate->min; in sof_ipc4_pcm_dai_link_fixup_rate()
647 struct snd_sof_dai *dai = snd_sof_find_dai(component, rtd->dai_link->name); in sof_ipc4_pcm_dai_link_fixup() local
657 if (!dai) { in sof_ipc4_pcm_dai_link_fixup()
658 dev_err(component->dev, "%s: No DAI found with name %s\n", __func__, in sof_ipc4_pcm_dai_link_fixup()
659 rtd->dai_link->name); in sof_ipc4_pcm_dai_link_fixup()
660 return -EINVAL; in sof_ipc4_pcm_dai_link_fixup()
663 ipc4_copier = dai->private; in sof_ipc4_pcm_dai_link_fixup()
665 dev_err(component->dev, "%s: No private data found for DAI %s\n", in sof_ipc4_pcm_dai_link_fixup()
666 __func__, rtd->dai_link->name); in sof_ipc4_pcm_dai_link_fixup()
667 return -EINVAL; in sof_ipc4_pcm_dai_link_fixup()
675 &ipc4_copier->available_fmt; in sof_ipc4_pcm_dai_link_fixup()
676 struct snd_sof_widget *swidget = w->dobj.private; in sof_ipc4_pcm_dai_link_fixup()
677 struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget; in sof_ipc4_pcm_dai_link_fixup()
678 struct sof_ipc4_pipeline *pipeline = pipe_widget->private; in sof_ipc4_pcm_dai_link_fixup()
681 if (pipeline->use_chain_dma) in sof_ipc4_pcm_dai_link_fixup()
686 available_fmt->output_pin_fmts, in sof_ipc4_pcm_dai_link_fixup()
687 available_fmt->num_output_formats)) { in sof_ipc4_pcm_dai_link_fixup()
688 ipc4_fmt = &available_fmt->output_pin_fmts->audio_fmt; in sof_ipc4_pcm_dai_link_fixup()
693 available_fmt->input_pin_fmts, in sof_ipc4_pcm_dai_link_fixup()
694 available_fmt->num_input_formats)) { in sof_ipc4_pcm_dai_link_fixup()
695 ipc4_fmt = &available_fmt->input_pin_fmts->audio_fmt; in sof_ipc4_pcm_dai_link_fixup()
708 valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(ipc4_fmt->fmt_cfg); in sof_ipc4_pcm_dai_link_fixup()
709 dev_dbg(component->dev, "Set %s to %d bit format\n", dai->name, valid_bits); in sof_ipc4_pcm_dai_link_fixup()
727 switch (ipc4_copier->dai_type) { in sof_ipc4_pcm_dai_link_fixup()
729 ipc4_ssp_dai_config_pcm_params_match(sdev, (char *)rtd->dai_link->name, params); in sof_ipc4_pcm_dai_link_fixup()
745 pipeline_list = &spcm->stream[stream].pipeline_list; in sof_ipc4_pcm_free()
746 kfree(pipeline_list->pipelines); in sof_ipc4_pcm_free()
747 pipeline_list->pipelines = NULL; in sof_ipc4_pcm_free()
749 stream_priv = spcm->stream[stream].private; in sof_ipc4_pcm_free()
750 kfree(stream_priv->time_info); in sof_ipc4_pcm_free()
751 kfree(spcm->stream[stream].private); in sof_ipc4_pcm_free()
752 spcm->stream[stream].private = NULL; in sof_ipc4_pcm_free()
759 struct sof_ipc4_fw_data *ipc4_data = sdev->private; in sof_ipc4_pcm_setup()
768 sof_mailbox_read(sdev, sdev->fw_info_box.offset + abi_offset, &abi_version, in sof_ipc4_pcm_setup()
775 if (!sof_ops(sdev) || !sof_ops(sdev)->get_host_byte_counter) in sof_ipc4_pcm_setup()
779 pipeline_list = &spcm->stream[stream].pipeline_list; in sof_ipc4_pcm_setup()
782 pipeline_list->pipelines = kcalloc(ipc4_data->max_num_pipelines, in sof_ipc4_pcm_setup()
784 if (!pipeline_list->pipelines) { in sof_ipc4_pcm_setup()
786 return -ENOMEM; in sof_ipc4_pcm_setup()
792 return -ENOMEM; in sof_ipc4_pcm_setup()
795 spcm->stream[stream].private = stream_priv; in sof_ipc4_pcm_setup()
803 return -ENOMEM; in sof_ipc4_pcm_setup()
806 stream_priv->time_info = time_info; in sof_ipc4_pcm_setup()
819 struct snd_sof_dai *dai; in sof_ipc4_build_time_info() local
822 /* find host & dai to locate info in memory window */ in sof_ipc4_build_time_info()
823 for_each_dapm_widgets(sps->list, i, widget) { in sof_ipc4_build_time_info()
824 struct snd_sof_widget *swidget = widget->dobj.private; in sof_ipc4_build_time_info()
829 if (WIDGET_IS_AIF(swidget->widget->id)) { in sof_ipc4_build_time_info()
830 host_copier = swidget->private; in sof_ipc4_build_time_info()
831 } else if (WIDGET_IS_DAI(swidget->widget->id)) { in sof_ipc4_build_time_info()
832 dai = swidget->private; in sof_ipc4_build_time_info()
833 dai_copier = dai->private; in sof_ipc4_build_time_info()
837 /* both host and dai copier must be valid for time_info */ in sof_ipc4_build_time_info()
839 dev_err(sdev->dev, "host or dai copier are not found\n"); in sof_ipc4_build_time_info()
844 time_info->host_copier = host_copier; in sof_ipc4_build_time_info()
845 time_info->dai_copier = dai_copier; in sof_ipc4_build_time_info()
846 time_info->llp_offset = offsetof(struct sof_ipc4_fw_registers, in sof_ipc4_build_time_info()
847 llp_gpdma_reading_slots) + sdev->fw_info_box.offset; in sof_ipc4_build_time_info()
849 /* find llp slot used by current dai */ in sof_ipc4_build_time_info()
851 sof_mailbox_read(sdev, time_info->llp_offset, &llp_slot, sizeof(llp_slot)); in sof_ipc4_build_time_info()
852 if (llp_slot.node_id == dai_copier->data.gtw_cfg.node_id) in sof_ipc4_build_time_info()
855 time_info->llp_offset += sizeof(llp_slot); in sof_ipc4_build_time_info()
862 time_info->llp_offset = offsetof(struct sof_ipc4_fw_registers, in sof_ipc4_build_time_info()
863 llp_sndw_reading_slots) + sdev->fw_info_box.offset; in sof_ipc4_build_time_info()
865 sof_mailbox_read(sdev, time_info->llp_offset, &llp_slot, sizeof(llp_slot)); in sof_ipc4_build_time_info()
866 if (llp_slot.node_id == dai_copier->data.gtw_cfg.node_id) in sof_ipc4_build_time_info()
869 time_info->llp_offset += sizeof(llp_slot); in sof_ipc4_build_time_info()
876 time_info->llp_offset = offsetof(struct sof_ipc4_fw_registers, in sof_ipc4_build_time_info()
877 llp_evad_reading_slot) + sdev->fw_info_box.offset; in sof_ipc4_build_time_info()
878 sof_mailbox_read(sdev, time_info->llp_offset, &llp_slot, sizeof(llp_slot)); in sof_ipc4_build_time_info()
879 if (llp_slot.node_id != dai_copier->data.gtw_cfg.node_id) in sof_ipc4_build_time_info()
880 time_info->llp_offset = 0; in sof_ipc4_build_time_info()
895 return -EINVAL; in sof_ipc4_pcm_hw_params()
897 time_info = sof_ipc4_sps_to_time_info(&spcm->stream[substream->stream]); in sof_ipc4_pcm_hw_params()
902 time_info->stream_start_offset = SOF_IPC4_INVALID_STREAM_POSITION; in sof_ipc4_pcm_hw_params()
903 time_info->llp_offset = 0; in sof_ipc4_pcm_hw_params()
905 sof_ipc4_build_time_info(sdev, &spcm->stream[substream->stream]); in sof_ipc4_pcm_hw_params()
915 struct sof_ipc4_copier *host_copier = time_info->host_copier; in sof_ipc4_get_stream_start_offset()
916 struct sof_ipc4_copier *dai_copier = time_info->dai_copier; in sof_ipc4_get_stream_start_offset()
923 return -EINVAL; in sof_ipc4_get_stream_start_offset()
925 if (host_copier->data.gtw_cfg.node_id == SOF_IPC4_INVALID_NODE_ID) in sof_ipc4_get_stream_start_offset()
926 return -EINVAL; in sof_ipc4_get_stream_start_offset()
928 node_index = SOF_IPC4_NODE_INDEX(host_copier->data.gtw_cfg.node_id); in sof_ipc4_get_stream_start_offset()
930 sof_mailbox_read(sdev, sdev->fw_info_box.offset + offset, &ppl_reg, sizeof(ppl_reg)); in sof_ipc4_get_stream_start_offset()
932 return -EINVAL; in sof_ipc4_get_stream_start_offset()
934 ch = dai_copier->data.out_format.fmt_cfg; in sof_ipc4_get_stream_start_offset()
936 dai_sample_size = (dai_copier->data.out_format.bit_depth >> 3) * ch; in sof_ipc4_get_stream_start_offset()
939 time_info->stream_start_offset = ppl_reg.stream_start_offset; in sof_ipc4_get_stream_start_offset()
940 do_div(time_info->stream_start_offset, dai_sample_size); in sof_ipc4_get_stream_start_offset()
941 time_info->stream_end_offset = ppl_reg.stream_end_offset; in sof_ipc4_get_stream_start_offset()
942 do_div(time_info->stream_end_offset, dai_sample_size); in sof_ipc4_get_stream_start_offset()
947 * based link counter. in sof_ipc4_get_stream_start_offset()
949 time_info->boundary = div64_u64(~((u64)0), in sof_ipc4_get_stream_start_offset()
950 frames_to_bytes(substream->runtime, 1)); in sof_ipc4_get_stream_start_offset()
952 time_info->delay = 0; in sof_ipc4_get_stream_start_offset()
973 return -EOPNOTSUPP; in sof_ipc4_pcm_pointer()
975 sps = &spcm->stream[substream->stream]; in sof_ipc4_pcm_pointer()
978 return -EOPNOTSUPP; in sof_ipc4_pcm_pointer()
985 if (time_info->stream_start_offset == SOF_IPC4_INVALID_STREAM_POSITION) { in sof_ipc4_pcm_pointer()
988 return -EOPNOTSUPP; in sof_ipc4_pcm_pointer()
996 host_cnt = div64_u64(host_cnt, frames_to_bytes(substream->runtime, 1)); in sof_ipc4_pcm_pointer()
1000 * then read the dai (link) counter via host accessible means if in sof_ipc4_pcm_pointer()
1003 if (!time_info->llp_offset) { in sof_ipc4_pcm_pointer()
1006 return -EOPNOTSUPP; in sof_ipc4_pcm_pointer()
1008 sof_mailbox_read(sdev, time_info->llp_offset, &llp, sizeof(llp)); in sof_ipc4_pcm_pointer()
1011 dai_cnt += time_info->stream_end_offset; in sof_ipc4_pcm_pointer()
1013 /* In two cases dai dma counter is not accurate in sof_ipc4_pcm_pointer()
1014 * (1) dai pipeline is started before host pipeline in sof_ipc4_pcm_pointer()
1015 * (2) multiple streams mixed into one. Each stream has the same dai dma in sof_ipc4_pcm_pointer()
1020 * Driver subtracts stream_start_offset from dai dma counter to get in sof_ipc4_pcm_pointer()
1025 * On stream start the dai counter might not yet have reached the in sof_ipc4_pcm_pointer()
1030 * increasing the host counter by (offset - dai_counter). in sof_ipc4_pcm_pointer()
1032 * of valid frames passed on the DAI side. in sof_ipc4_pcm_pointer()
1037 if (dai_cnt < time_info->stream_start_offset) { in sof_ipc4_pcm_pointer()
1038 host_cnt += time_info->stream_start_offset - dai_cnt; in sof_ipc4_pcm_pointer()
1041 dai_cnt -= time_info->stream_start_offset; in sof_ipc4_pcm_pointer()
1044 /* Wrap the dai counter at the boundary where the host counter wraps */ in sof_ipc4_pcm_pointer()
1045 div64_u64_rem(dai_cnt, time_info->boundary, &dai_cnt); in sof_ipc4_pcm_pointer()
1047 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { in sof_ipc4_pcm_pointer()
1056 time_info->delay = time_info->boundary - tail_cnt + head_cnt; in sof_ipc4_pcm_pointer()
1060 time_info->delay = head_cnt - tail_cnt; in sof_ipc4_pcm_pointer()
1068 *pointer = bytes_to_frames(substream->runtime, host_ptr); in sof_ipc4_pcm_pointer()
1084 time_info = sof_ipc4_sps_to_time_info(&spcm->stream[substream->stream]); in sof_ipc4_pcm_delay()
1091 return time_info->delay; in sof_ipc4_pcm_delay()