Revert "unicode: Don't special case ignorable code points"
[linux.git] / sound / soc / sof / intel / hda-dai-ops.c
blob92681ca7f24def1307f9a3b7d6e1fc009e566953
1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
2 //
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.
5 //
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"
18 #include "hda.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)
38 return true;
41 return false;
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;
56 if (!bus->ppcap) {
57 dev_err(bus->dev, "stream type not supported\n");
58 return NULL;
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)
66 continue;
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)) {
79 res = hext_stream;
80 break;
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)) {
90 res = hext_stream;
91 break;
93 } else {
94 res = hext_stream;
97 * This must be a hostless stream.
98 * So reserve the host DMA channel.
100 hda_stream->host_reserved = 1;
101 break;
106 if (res) {
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);
115 return res;
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);
152 if (!hext_stream)
153 return NULL;
155 snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)hext_stream);
157 return 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;
199 unsigned int bits;
201 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
202 link_bps = codec_dai->driver->playback.sig_bits;
203 else
204 link_bps = codec_dai->driver->capture.sig_bits;
206 bits = snd_hdac_stream_format_bits(params_format(params), SNDRV_PCM_SUBFORMAT_STD,
207 link_bps);
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));
213 return format_val;
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;
231 unsigned int bits;
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));
240 return format_val;
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;
250 unsigned int width;
251 unsigned int bits;
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;
259 channels /= 2;
260 width = 32;
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);
269 return format_val;
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;
304 int ret = 0;
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)
312 return 0;
314 mutex_lock(&ipc4_data->pipeline_state_mutex);
316 switch (cmd) {
317 case SNDRV_PCM_TRIGGER_START:
318 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
319 break;
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);
325 if (ret < 0)
326 goto out;
328 pipeline->state = SOF_IPC4_PIPE_PAUSED;
329 break;
330 default:
331 dev_err(sdev->dev, "unknown trigger command %d\n", cmd);
332 ret = -EINVAL;
334 out:
335 mutex_unlock(&ipc4_data->pipeline_state_mutex);
336 return ret;
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);
344 switch (cmd) {
345 case SNDRV_PCM_TRIGGER_START:
346 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
347 snd_hdac_ext_stream_start(hext_stream);
348 break;
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);
358 break;
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);
364 break;
365 default:
366 dev_err(sdev->dev, "unknown trigger command %d\n", cmd);
367 return -EINVAL;
370 return 0;
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;
381 int ret = 0;
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)
389 return 0;
391 mutex_lock(&ipc4_data->pipeline_state_mutex);
393 switch (cmd) {
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);
398 if (ret < 0)
399 goto out;
400 pipeline->state = SOF_IPC4_PIPE_PAUSED;
403 ret = sof_ipc4_set_pipeline_state(sdev, pipe_widget->instance_id,
404 SOF_IPC4_PIPE_RUNNING);
405 if (ret < 0)
406 goto out;
407 pipeline->state = SOF_IPC4_PIPE_RUNNING;
408 swidget->spipe->started_count++;
409 break;
410 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
411 ret = sof_ipc4_set_pipeline_state(sdev, pipe_widget->instance_id,
412 SOF_IPC4_PIPE_RUNNING);
413 if (ret < 0)
414 goto out;
415 pipeline->state = SOF_IPC4_PIPE_RUNNING;
416 break;
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;
424 break;
425 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
426 break;
427 default:
428 dev_err(sdev->dev, "unknown trigger command %d\n", cmd);
429 ret = -EINVAL;
430 break;
432 out:
433 mutex_unlock(&ipc4_data->pipeline_state_mutex);
434 return ret;
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);
518 switch (cmd) {
519 case SNDRV_PCM_TRIGGER_SUSPEND:
520 case SNDRV_PCM_TRIGGER_STOP:
522 struct snd_sof_dai_config_data data = { 0 };
523 int ret;
525 data.dai_data = DMA_CHAN_INVALID;
526 ret = hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_HW_FREE, &data);
527 if (ret < 0)
528 return ret;
530 break;
532 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
533 return hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_PAUSE, NULL);
534 default:
535 break;
538 return 0;
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
570 * using dummy_codec.
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,
590 #endif
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)
608 return NULL;
609 return &sdw_dspless_dma_ops;
610 default:
611 return NULL;
615 switch (sdev->pdata->ipc_type) {
616 case SOF_IPC_TYPE_3:
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;
622 break;
624 case SOF_IPC_TYPE_4:
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)
637 return NULL;
638 return &ssp_ipc4_dma_ops;
639 case SOF_DAI_INTEL_DMIC:
640 if (chip->hw_ip_version < SOF_INTEL_ACE_2_0)
641 return NULL;
642 return &dmic_ipc4_dma_ops;
643 case SOF_DAI_INTEL_ALH:
644 if (chip->hw_ip_version < SOF_INTEL_ACE_2_0)
645 return NULL;
646 if (pipeline->use_chain_dma)
647 return &sdw_ipc4_chain_dma_ops;
648 return &sdw_ipc4_dma_ops;
650 default:
651 break;
653 break;
655 default:
656 break;
658 #endif
659 return NULL;