1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
3 // This file is provided under a dual BSD/GPLv2 license. When using or
4 // redistributing this file, you may do so under either license.
6 // Copyright(c) 2022 Intel Corporation
8 #include <sound/pcm_params.h>
9 #include <sound/hdaudio_ext.h>
10 #include <sound/hda_register.h>
11 #include <sound/hda-mlink.h>
12 #include <sound/sof/ipc4/header.h>
13 #include <uapi/sound/sof/header.h>
14 #include "../ipc4-priv.h"
15 #include "../ipc4-topology.h"
16 #include "../sof-priv.h"
17 #include "../sof-audio.h"
20 /* These ops are only applicable for the HDA DAI's in their current form */
21 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_LINK)
23 * This function checks if the host dma channel corresponding
24 * to the link DMA stream_tag argument is assigned to one
25 * of the FEs connected to the BE DAI.
27 static bool hda_check_fes(struct snd_soc_pcm_runtime
*rtd
,
28 int dir
, int stream_tag
)
30 struct snd_pcm_substream
*fe_substream
;
31 struct hdac_stream
*fe_hstream
;
32 struct snd_soc_dpcm
*dpcm
;
34 for_each_dpcm_fe(rtd
, dir
, dpcm
) {
35 fe_substream
= snd_soc_dpcm_get_substream(dpcm
->fe
, dir
);
36 fe_hstream
= fe_substream
->runtime
->private_data
;
37 if (fe_hstream
->stream_tag
== stream_tag
)
44 static struct hdac_ext_stream
*
45 hda_link_stream_assign(struct hdac_bus
*bus
, struct snd_pcm_substream
*substream
)
47 struct snd_soc_pcm_runtime
*rtd
= snd_soc_substream_to_rtd(substream
);
48 struct sof_intel_hda_stream
*hda_stream
;
49 const struct sof_intel_dsp_desc
*chip
;
50 struct snd_sof_dev
*sdev
;
51 struct hdac_ext_stream
*res
= NULL
;
52 struct hdac_stream
*hstream
= NULL
;
54 int stream_dir
= substream
->stream
;
57 dev_err(bus
->dev
, "stream type not supported\n");
61 spin_lock_irq(&bus
->reg_lock
);
62 list_for_each_entry(hstream
, &bus
->stream_list
, list
) {
63 struct hdac_ext_stream
*hext_stream
=
64 stream_to_hdac_ext_stream(hstream
);
65 if (hstream
->direction
!= substream
->stream
)
68 hda_stream
= hstream_to_sof_hda_stream(hext_stream
);
69 sdev
= hda_stream
->sdev
;
70 chip
= get_chip_info(sdev
->pdata
);
72 /* check if link is available */
73 if (!hext_stream
->link_locked
) {
75 * choose the first available link for platforms that do not have the
76 * PROCEN_FMT_QUIRK set.
78 if (!(chip
->quirks
& SOF_INTEL_PROCEN_FMT_QUIRK
)) {
83 if (hstream
->opened
) {
85 * check if the stream tag matches the stream
86 * tag of one of the connected FEs
88 if (hda_check_fes(rtd
, stream_dir
,
89 hstream
->stream_tag
)) {
97 * This must be a hostless stream.
98 * So reserve the host DMA channel.
100 hda_stream
->host_reserved
= 1;
107 /* Make sure that host and link DMA is decoupled. */
108 snd_hdac_ext_stream_decouple_locked(bus
, res
, true);
110 res
->link_locked
= 1;
111 res
->link_substream
= substream
;
113 spin_unlock_irq(&bus
->reg_lock
);
118 static struct hdac_ext_stream
*hda_get_hext_stream(struct snd_sof_dev
*sdev
,
119 struct snd_soc_dai
*cpu_dai
,
120 struct snd_pcm_substream
*substream
)
122 return snd_soc_dai_get_dma_data(cpu_dai
, substream
);
125 static struct hdac_ext_stream
*hda_ipc4_get_hext_stream(struct snd_sof_dev
*sdev
,
126 struct snd_soc_dai
*cpu_dai
,
127 struct snd_pcm_substream
*substream
)
129 struct snd_sof_widget
*pipe_widget
;
130 struct sof_ipc4_pipeline
*pipeline
;
131 struct snd_sof_widget
*swidget
;
132 struct snd_soc_dapm_widget
*w
;
134 w
= snd_soc_dai_get_widget(cpu_dai
, substream
->stream
);
135 swidget
= w
->dobj
.private;
136 pipe_widget
= swidget
->spipe
->pipe_widget
;
137 pipeline
= pipe_widget
->private;
139 /* mark pipeline so that it can be skipped during FE trigger */
140 pipeline
->skip_during_fe_trigger
= true;
142 return snd_soc_dai_get_dma_data(cpu_dai
, substream
);
145 static struct hdac_ext_stream
*hda_assign_hext_stream(struct snd_sof_dev
*sdev
,
146 struct snd_soc_dai
*cpu_dai
,
147 struct snd_pcm_substream
*substream
)
149 struct hdac_ext_stream
*hext_stream
;
151 hext_stream
= hda_link_stream_assign(sof_to_bus(sdev
), substream
);
155 snd_soc_dai_set_dma_data(cpu_dai
, substream
, (void *)hext_stream
);
160 static void hda_release_hext_stream(struct snd_sof_dev
*sdev
, struct snd_soc_dai
*cpu_dai
,
161 struct snd_pcm_substream
*substream
)
163 struct hdac_ext_stream
*hext_stream
= hda_get_hext_stream(sdev
, cpu_dai
, substream
);
165 snd_soc_dai_set_dma_data(cpu_dai
, substream
, NULL
);
166 snd_hdac_ext_stream_release(hext_stream
, HDAC_EXT_STREAM_TYPE_LINK
);
169 static void hda_setup_hext_stream(struct snd_sof_dev
*sdev
, struct hdac_ext_stream
*hext_stream
,
170 unsigned int format_val
)
172 snd_hdac_ext_stream_setup(hext_stream
, format_val
);
175 static void hda_reset_hext_stream(struct snd_sof_dev
*sdev
, struct hdac_ext_stream
*hext_stream
)
177 snd_hdac_ext_stream_reset(hext_stream
);
180 static void hda_codec_dai_set_stream(struct snd_sof_dev
*sdev
,
181 struct snd_pcm_substream
*substream
,
182 struct hdac_stream
*hstream
)
184 struct snd_soc_pcm_runtime
*rtd
= snd_soc_substream_to_rtd(substream
);
185 struct snd_soc_dai
*codec_dai
= snd_soc_rtd_to_codec(rtd
, 0);
187 /* set the hdac_stream in the codec dai */
188 snd_soc_dai_set_stream(codec_dai
, hstream
, substream
->stream
);
191 static unsigned int hda_calc_stream_format(struct snd_sof_dev
*sdev
,
192 struct snd_pcm_substream
*substream
,
193 struct snd_pcm_hw_params
*params
)
195 struct snd_soc_pcm_runtime
*rtd
= snd_soc_substream_to_rtd(substream
);
196 struct snd_soc_dai
*codec_dai
= snd_soc_rtd_to_codec(rtd
, 0);
197 unsigned int link_bps
;
198 unsigned int format_val
;
201 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
)
202 link_bps
= codec_dai
->driver
->playback
.sig_bits
;
204 link_bps
= codec_dai
->driver
->capture
.sig_bits
;
206 bits
= snd_hdac_stream_format_bits(params_format(params
), SNDRV_PCM_SUBFORMAT_STD
,
208 format_val
= snd_hdac_stream_format(params_channels(params
), bits
, params_rate(params
));
210 dev_dbg(sdev
->dev
, "format_val=%#x, rate=%d, ch=%d, format=%d\n", format_val
,
211 params_rate(params
), params_channels(params
), params_format(params
));
216 static struct hdac_ext_link
*hda_get_hlink(struct snd_sof_dev
*sdev
,
217 struct snd_pcm_substream
*substream
)
219 struct snd_soc_pcm_runtime
*rtd
= snd_soc_substream_to_rtd(substream
);
220 struct snd_soc_dai
*codec_dai
= snd_soc_rtd_to_codec(rtd
, 0);
221 struct hdac_bus
*bus
= sof_to_bus(sdev
);
223 return snd_hdac_ext_bus_get_hlink_by_name(bus
, codec_dai
->component
->name
);
226 static unsigned int generic_calc_stream_format(struct snd_sof_dev
*sdev
,
227 struct snd_pcm_substream
*substream
,
228 struct snd_pcm_hw_params
*params
)
230 unsigned int format_val
;
233 bits
= snd_hdac_stream_format_bits(params_format(params
), SNDRV_PCM_SUBFORMAT_STD
,
234 params_physical_width(params
));
235 format_val
= snd_hdac_stream_format(params_channels(params
), bits
, params_rate(params
));
237 dev_dbg(sdev
->dev
, "format_val=%#x, rate=%d, ch=%d, format=%d\n", format_val
,
238 params_rate(params
), params_channels(params
), params_format(params
));
243 static unsigned int dmic_calc_stream_format(struct snd_sof_dev
*sdev
,
244 struct snd_pcm_substream
*substream
,
245 struct snd_pcm_hw_params
*params
)
247 unsigned int format_val
;
248 snd_pcm_format_t format
;
249 unsigned int channels
;
253 channels
= params_channels(params
);
254 format
= params_format(params
);
255 width
= params_physical_width(params
);
257 if (format
== SNDRV_PCM_FORMAT_S16_LE
) {
258 format
= SNDRV_PCM_FORMAT_S32_LE
;
263 bits
= snd_hdac_stream_format_bits(format
, SNDRV_PCM_SUBFORMAT_STD
, width
);
264 format_val
= snd_hdac_stream_format(channels
, bits
, params_rate(params
));
266 dev_dbg(sdev
->dev
, "format_val=%#x, rate=%d, ch=%d, format=%d\n", format_val
,
267 params_rate(params
), channels
, format
);
272 static struct hdac_ext_link
*ssp_get_hlink(struct snd_sof_dev
*sdev
,
273 struct snd_pcm_substream
*substream
)
275 struct hdac_bus
*bus
= sof_to_bus(sdev
);
277 return hdac_bus_eml_ssp_get_hlink(bus
);
280 static struct hdac_ext_link
*dmic_get_hlink(struct snd_sof_dev
*sdev
,
281 struct snd_pcm_substream
*substream
)
283 struct hdac_bus
*bus
= sof_to_bus(sdev
);
285 return hdac_bus_eml_dmic_get_hlink(bus
);
288 static struct hdac_ext_link
*sdw_get_hlink(struct snd_sof_dev
*sdev
,
289 struct snd_pcm_substream
*substream
)
291 struct hdac_bus
*bus
= sof_to_bus(sdev
);
293 return hdac_bus_eml_sdw_get_hlink(bus
);
296 static int hda_ipc4_pre_trigger(struct snd_sof_dev
*sdev
, struct snd_soc_dai
*cpu_dai
,
297 struct snd_pcm_substream
*substream
, int cmd
)
299 struct sof_ipc4_fw_data
*ipc4_data
= sdev
->private;
300 struct snd_sof_widget
*pipe_widget
;
301 struct sof_ipc4_pipeline
*pipeline
;
302 struct snd_sof_widget
*swidget
;
303 struct snd_soc_dapm_widget
*w
;
306 w
= snd_soc_dai_get_widget(cpu_dai
, substream
->stream
);
307 swidget
= w
->dobj
.private;
308 pipe_widget
= swidget
->spipe
->pipe_widget
;
309 pipeline
= pipe_widget
->private;
311 if (pipe_widget
->instance_id
< 0)
314 mutex_lock(&ipc4_data
->pipeline_state_mutex
);
317 case SNDRV_PCM_TRIGGER_START
:
318 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
320 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
321 case SNDRV_PCM_TRIGGER_SUSPEND
:
322 case SNDRV_PCM_TRIGGER_STOP
:
323 ret
= sof_ipc4_set_pipeline_state(sdev
, pipe_widget
->instance_id
,
324 SOF_IPC4_PIPE_PAUSED
);
328 pipeline
->state
= SOF_IPC4_PIPE_PAUSED
;
331 dev_err(sdev
->dev
, "unknown trigger command %d\n", cmd
);
335 mutex_unlock(&ipc4_data
->pipeline_state_mutex
);
339 static int hda_trigger(struct snd_sof_dev
*sdev
, struct snd_soc_dai
*cpu_dai
,
340 struct snd_pcm_substream
*substream
, int cmd
)
342 struct hdac_ext_stream
*hext_stream
= snd_soc_dai_get_dma_data(cpu_dai
, substream
);
345 case SNDRV_PCM_TRIGGER_START
:
346 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
347 snd_hdac_ext_stream_start(hext_stream
);
349 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
351 * Save the LLP registers since in case of PAUSE the LLP
352 * register are not reset to 0, the delay calculation will use
353 * the saved offsets for compensating the delay calculation.
355 hext_stream
->pplcllpl
= readl(hext_stream
->pplc_addr
+ AZX_REG_PPLCLLPL
);
356 hext_stream
->pplcllpu
= readl(hext_stream
->pplc_addr
+ AZX_REG_PPLCLLPU
);
357 snd_hdac_ext_stream_clear(hext_stream
);
359 case SNDRV_PCM_TRIGGER_SUSPEND
:
360 case SNDRV_PCM_TRIGGER_STOP
:
361 hext_stream
->pplcllpl
= 0;
362 hext_stream
->pplcllpu
= 0;
363 snd_hdac_ext_stream_clear(hext_stream
);
366 dev_err(sdev
->dev
, "unknown trigger command %d\n", cmd
);
373 static int hda_ipc4_post_trigger(struct snd_sof_dev
*sdev
, struct snd_soc_dai
*cpu_dai
,
374 struct snd_pcm_substream
*substream
, int cmd
)
376 struct sof_ipc4_fw_data
*ipc4_data
= sdev
->private;
377 struct snd_sof_widget
*pipe_widget
;
378 struct sof_ipc4_pipeline
*pipeline
;
379 struct snd_sof_widget
*swidget
;
380 struct snd_soc_dapm_widget
*w
;
383 w
= snd_soc_dai_get_widget(cpu_dai
, substream
->stream
);
384 swidget
= w
->dobj
.private;
385 pipe_widget
= swidget
->spipe
->pipe_widget
;
386 pipeline
= pipe_widget
->private;
388 if (pipe_widget
->instance_id
< 0)
391 mutex_lock(&ipc4_data
->pipeline_state_mutex
);
394 case SNDRV_PCM_TRIGGER_START
:
395 if (pipeline
->state
!= SOF_IPC4_PIPE_PAUSED
) {
396 ret
= sof_ipc4_set_pipeline_state(sdev
, pipe_widget
->instance_id
,
397 SOF_IPC4_PIPE_PAUSED
);
400 pipeline
->state
= SOF_IPC4_PIPE_PAUSED
;
403 ret
= sof_ipc4_set_pipeline_state(sdev
, pipe_widget
->instance_id
,
404 SOF_IPC4_PIPE_RUNNING
);
407 pipeline
->state
= SOF_IPC4_PIPE_RUNNING
;
408 swidget
->spipe
->started_count
++;
410 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
411 ret
= sof_ipc4_set_pipeline_state(sdev
, pipe_widget
->instance_id
,
412 SOF_IPC4_PIPE_RUNNING
);
415 pipeline
->state
= SOF_IPC4_PIPE_RUNNING
;
417 case SNDRV_PCM_TRIGGER_SUSPEND
:
418 case SNDRV_PCM_TRIGGER_STOP
:
420 * STOP/SUSPEND trigger is invoked only once when all users of this pipeline have
421 * been stopped. So, clear the started_count so that the pipeline can be reset
423 swidget
->spipe
->started_count
= 0;
425 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
428 dev_err(sdev
->dev
, "unknown trigger command %d\n", cmd
);
433 mutex_unlock(&ipc4_data
->pipeline_state_mutex
);
437 static const struct hda_dai_widget_dma_ops hda_ipc4_dma_ops
= {
438 .get_hext_stream
= hda_ipc4_get_hext_stream
,
439 .assign_hext_stream
= hda_assign_hext_stream
,
440 .release_hext_stream
= hda_release_hext_stream
,
441 .setup_hext_stream
= hda_setup_hext_stream
,
442 .reset_hext_stream
= hda_reset_hext_stream
,
443 .pre_trigger
= hda_ipc4_pre_trigger
,
444 .trigger
= hda_trigger
,
445 .post_trigger
= hda_ipc4_post_trigger
,
446 .codec_dai_set_stream
= hda_codec_dai_set_stream
,
447 .calc_stream_format
= hda_calc_stream_format
,
448 .get_hlink
= hda_get_hlink
,
451 static const struct hda_dai_widget_dma_ops ssp_ipc4_dma_ops
= {
452 .get_hext_stream
= hda_ipc4_get_hext_stream
,
453 .assign_hext_stream
= hda_assign_hext_stream
,
454 .release_hext_stream
= hda_release_hext_stream
,
455 .setup_hext_stream
= hda_setup_hext_stream
,
456 .reset_hext_stream
= hda_reset_hext_stream
,
457 .pre_trigger
= hda_ipc4_pre_trigger
,
458 .trigger
= hda_trigger
,
459 .post_trigger
= hda_ipc4_post_trigger
,
460 .calc_stream_format
= generic_calc_stream_format
,
461 .get_hlink
= ssp_get_hlink
,
464 static const struct hda_dai_widget_dma_ops dmic_ipc4_dma_ops
= {
465 .get_hext_stream
= hda_ipc4_get_hext_stream
,
466 .assign_hext_stream
= hda_assign_hext_stream
,
467 .release_hext_stream
= hda_release_hext_stream
,
468 .setup_hext_stream
= hda_setup_hext_stream
,
469 .reset_hext_stream
= hda_reset_hext_stream
,
470 .pre_trigger
= hda_ipc4_pre_trigger
,
471 .trigger
= hda_trigger
,
472 .post_trigger
= hda_ipc4_post_trigger
,
473 .calc_stream_format
= dmic_calc_stream_format
,
474 .get_hlink
= dmic_get_hlink
,
477 static const struct hda_dai_widget_dma_ops sdw_ipc4_dma_ops
= {
478 .get_hext_stream
= hda_ipc4_get_hext_stream
,
479 .assign_hext_stream
= hda_assign_hext_stream
,
480 .release_hext_stream
= hda_release_hext_stream
,
481 .setup_hext_stream
= hda_setup_hext_stream
,
482 .reset_hext_stream
= hda_reset_hext_stream
,
483 .pre_trigger
= hda_ipc4_pre_trigger
,
484 .trigger
= hda_trigger
,
485 .post_trigger
= hda_ipc4_post_trigger
,
486 .calc_stream_format
= generic_calc_stream_format
,
487 .get_hlink
= sdw_get_hlink
,
490 static const struct hda_dai_widget_dma_ops hda_ipc4_chain_dma_ops
= {
491 .get_hext_stream
= hda_get_hext_stream
,
492 .assign_hext_stream
= hda_assign_hext_stream
,
493 .release_hext_stream
= hda_release_hext_stream
,
494 .setup_hext_stream
= hda_setup_hext_stream
,
495 .reset_hext_stream
= hda_reset_hext_stream
,
496 .trigger
= hda_trigger
,
497 .codec_dai_set_stream
= hda_codec_dai_set_stream
,
498 .calc_stream_format
= hda_calc_stream_format
,
499 .get_hlink
= hda_get_hlink
,
502 static const struct hda_dai_widget_dma_ops sdw_ipc4_chain_dma_ops
= {
503 .get_hext_stream
= hda_get_hext_stream
,
504 .assign_hext_stream
= hda_assign_hext_stream
,
505 .release_hext_stream
= hda_release_hext_stream
,
506 .setup_hext_stream
= hda_setup_hext_stream
,
507 .reset_hext_stream
= hda_reset_hext_stream
,
508 .trigger
= hda_trigger
,
509 .calc_stream_format
= generic_calc_stream_format
,
510 .get_hlink
= sdw_get_hlink
,
513 static int hda_ipc3_post_trigger(struct snd_sof_dev
*sdev
, struct snd_soc_dai
*cpu_dai
,
514 struct snd_pcm_substream
*substream
, int cmd
)
516 struct snd_soc_dapm_widget
*w
= snd_soc_dai_get_widget(cpu_dai
, substream
->stream
);
519 case SNDRV_PCM_TRIGGER_SUSPEND
:
520 case SNDRV_PCM_TRIGGER_STOP
:
522 struct snd_sof_dai_config_data data
= { 0 };
525 data
.dai_data
= DMA_CHAN_INVALID
;
526 ret
= hda_dai_config(w
, SOF_DAI_CONFIG_FLAGS_HW_FREE
, &data
);
532 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
533 return hda_dai_config(w
, SOF_DAI_CONFIG_FLAGS_PAUSE
, NULL
);
541 static const struct hda_dai_widget_dma_ops hda_ipc3_dma_ops
= {
542 .get_hext_stream
= hda_get_hext_stream
,
543 .assign_hext_stream
= hda_assign_hext_stream
,
544 .release_hext_stream
= hda_release_hext_stream
,
545 .setup_hext_stream
= hda_setup_hext_stream
,
546 .reset_hext_stream
= hda_reset_hext_stream
,
547 .trigger
= hda_trigger
,
548 .post_trigger
= hda_ipc3_post_trigger
,
549 .codec_dai_set_stream
= hda_codec_dai_set_stream
,
550 .calc_stream_format
= hda_calc_stream_format
,
551 .get_hlink
= hda_get_hlink
,
554 static struct hdac_ext_stream
*
555 hda_dspless_get_hext_stream(struct snd_sof_dev
*sdev
, struct snd_soc_dai
*cpu_dai
,
556 struct snd_pcm_substream
*substream
)
558 struct hdac_stream
*hstream
= substream
->runtime
->private_data
;
560 return stream_to_hdac_ext_stream(hstream
);
563 static void hda_dspless_setup_hext_stream(struct snd_sof_dev
*sdev
,
564 struct hdac_ext_stream
*hext_stream
,
565 unsigned int format_val
)
568 * Save the format_val which was adjusted by the maxbps of the codec.
569 * This information is not available on the FE side since there we are
572 hext_stream
->hstream
.format_val
= format_val
;
575 static const struct hda_dai_widget_dma_ops hda_dspless_dma_ops
= {
576 .get_hext_stream
= hda_dspless_get_hext_stream
,
577 .setup_hext_stream
= hda_dspless_setup_hext_stream
,
578 .codec_dai_set_stream
= hda_codec_dai_set_stream
,
579 .calc_stream_format
= hda_calc_stream_format
,
580 .get_hlink
= hda_get_hlink
,
583 static const struct hda_dai_widget_dma_ops sdw_dspless_dma_ops
= {
584 .get_hext_stream
= hda_dspless_get_hext_stream
,
585 .setup_hext_stream
= hda_dspless_setup_hext_stream
,
586 .calc_stream_format
= generic_calc_stream_format
,
587 .get_hlink
= sdw_get_hlink
,
592 const struct hda_dai_widget_dma_ops
*
593 hda_select_dai_widget_ops(struct snd_sof_dev
*sdev
, struct snd_sof_widget
*swidget
)
595 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_LINK)
596 struct snd_sof_dai
*sdai
;
597 const struct sof_intel_dsp_desc
*chip
;
599 chip
= get_chip_info(sdev
->pdata
);
600 sdai
= swidget
->private;
602 if (sdev
->dspless_mode_selected
) {
603 switch (sdai
->type
) {
604 case SOF_DAI_INTEL_HDA
:
605 return &hda_dspless_dma_ops
;
606 case SOF_DAI_INTEL_ALH
:
607 if (chip
->hw_ip_version
< SOF_INTEL_ACE_2_0
)
609 return &sdw_dspless_dma_ops
;
615 switch (sdev
->pdata
->ipc_type
) {
618 struct sof_dai_private_data
*private = sdai
->private;
620 if (private->dai_config
->type
== SOF_DAI_INTEL_HDA
)
621 return &hda_ipc3_dma_ops
;
626 struct snd_sof_widget
*pipe_widget
= swidget
->spipe
->pipe_widget
;
627 struct sof_ipc4_pipeline
*pipeline
= pipe_widget
->private;
629 switch (sdai
->type
) {
630 case SOF_DAI_INTEL_HDA
:
631 if (pipeline
->use_chain_dma
)
632 return &hda_ipc4_chain_dma_ops
;
634 return &hda_ipc4_dma_ops
;
635 case SOF_DAI_INTEL_SSP
:
636 if (chip
->hw_ip_version
< SOF_INTEL_ACE_2_0
)
638 return &ssp_ipc4_dma_ops
;
639 case SOF_DAI_INTEL_DMIC
:
640 if (chip
->hw_ip_version
< SOF_INTEL_ACE_2_0
)
642 return &dmic_ipc4_dma_ops
;
643 case SOF_DAI_INTEL_ALH
:
644 if (chip
->hw_ip_version
< SOF_INTEL_ACE_2_0
)
646 if (pipeline
->use_chain_dma
)
647 return &sdw_ipc4_chain_dma_ops
;
648 return &sdw_ipc4_dma_ops
;