ASoC: Merge up fixes
[platform/kernel/linux-starfive.git] / sound / soc / sof / intel / hda-dai-ops.c
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. All rights reserved.
7
8 #include <sound/pcm_params.h>
9 #include <sound/hdaudio_ext.h>
10 #include <sound/hda-mlink.h>
11 #include <sound/sof/ipc4/header.h>
12 #include <uapi/sound/sof/header.h>
13 #include "../ipc4-priv.h"
14 #include "../ipc4-topology.h"
15 #include "../sof-priv.h"
16 #include "../sof-audio.h"
17 #include "hda.h"
18
19 /* These ops are only applicable for the HDA DAI's in their current form */
20 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_LINK)
21 /*
22  * This function checks if the host dma channel corresponding
23  * to the link DMA stream_tag argument is assigned to one
24  * of the FEs connected to the BE DAI.
25  */
26 static bool hda_check_fes(struct snd_soc_pcm_runtime *rtd,
27                           int dir, int stream_tag)
28 {
29         struct snd_pcm_substream *fe_substream;
30         struct hdac_stream *fe_hstream;
31         struct snd_soc_dpcm *dpcm;
32
33         for_each_dpcm_fe(rtd, dir, dpcm) {
34                 fe_substream = snd_soc_dpcm_get_substream(dpcm->fe, dir);
35                 fe_hstream = fe_substream->runtime->private_data;
36                 if (fe_hstream->stream_tag == stream_tag)
37                         return true;
38         }
39
40         return false;
41 }
42
43 static struct hdac_ext_stream *
44 hda_link_stream_assign(struct hdac_bus *bus, struct snd_pcm_substream *substream)
45 {
46         struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
47         struct sof_intel_hda_stream *hda_stream;
48         const struct sof_intel_dsp_desc *chip;
49         struct snd_sof_dev *sdev;
50         struct hdac_ext_stream *res = NULL;
51         struct hdac_stream *hstream = NULL;
52
53         int stream_dir = substream->stream;
54
55         if (!bus->ppcap) {
56                 dev_err(bus->dev, "stream type not supported\n");
57                 return NULL;
58         }
59
60         spin_lock_irq(&bus->reg_lock);
61         list_for_each_entry(hstream, &bus->stream_list, list) {
62                 struct hdac_ext_stream *hext_stream =
63                         stream_to_hdac_ext_stream(hstream);
64                 if (hstream->direction != substream->stream)
65                         continue;
66
67                 hda_stream = hstream_to_sof_hda_stream(hext_stream);
68                 sdev = hda_stream->sdev;
69                 chip = get_chip_info(sdev->pdata);
70
71                 /* check if link is available */
72                 if (!hext_stream->link_locked) {
73                         /*
74                          * choose the first available link for platforms that do not have the
75                          * PROCEN_FMT_QUIRK set.
76                          */
77                         if (!(chip->quirks & SOF_INTEL_PROCEN_FMT_QUIRK)) {
78                                 res = hext_stream;
79                                 break;
80                         }
81
82                         if (hstream->opened) {
83                                 /*
84                                  * check if the stream tag matches the stream
85                                  * tag of one of the connected FEs
86                                  */
87                                 if (hda_check_fes(rtd, stream_dir,
88                                                   hstream->stream_tag)) {
89                                         res = hext_stream;
90                                         break;
91                                 }
92                         } else {
93                                 res = hext_stream;
94
95                                 /*
96                                  * This must be a hostless stream.
97                                  * So reserve the host DMA channel.
98                                  */
99                                 hda_stream->host_reserved = 1;
100                                 break;
101                         }
102                 }
103         }
104
105         if (res) {
106                 /* Make sure that host and link DMA is decoupled. */
107                 snd_hdac_ext_stream_decouple_locked(bus, res, true);
108
109                 res->link_locked = 1;
110                 res->link_substream = substream;
111         }
112         spin_unlock_irq(&bus->reg_lock);
113
114         return res;
115 }
116
117 static struct hdac_ext_stream *hda_get_hext_stream(struct snd_sof_dev *sdev,
118                                                    struct snd_soc_dai *cpu_dai,
119                                                    struct snd_pcm_substream *substream)
120 {
121         return snd_soc_dai_get_dma_data(cpu_dai, substream);
122 }
123
124 static struct hdac_ext_stream *hda_ipc4_get_hext_stream(struct snd_sof_dev *sdev,
125                                                         struct snd_soc_dai *cpu_dai,
126                                                         struct snd_pcm_substream *substream)
127 {
128         struct snd_sof_widget *pipe_widget;
129         struct sof_ipc4_pipeline *pipeline;
130         struct snd_sof_widget *swidget;
131         struct snd_soc_dapm_widget *w;
132
133         w = snd_soc_dai_get_widget(cpu_dai, substream->stream);
134         swidget = w->dobj.private;
135         pipe_widget = swidget->spipe->pipe_widget;
136         pipeline = pipe_widget->private;
137
138         /* mark pipeline so that it can be skipped during FE trigger */
139         pipeline->skip_during_fe_trigger = true;
140
141         return snd_soc_dai_get_dma_data(cpu_dai, substream);
142 }
143
144 static struct hdac_ext_stream *hda_assign_hext_stream(struct snd_sof_dev *sdev,
145                                                       struct snd_soc_dai *cpu_dai,
146                                                       struct snd_pcm_substream *substream)
147 {
148         struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
149         struct snd_soc_dai *dai;
150         struct hdac_ext_stream *hext_stream;
151
152         /* only allocate a stream_tag for the first DAI in the dailink */
153         dai = asoc_rtd_to_cpu(rtd, 0);
154         if (dai == cpu_dai)
155                 hext_stream = hda_link_stream_assign(sof_to_bus(sdev), substream);
156         else
157                 hext_stream = snd_soc_dai_get_dma_data(dai, substream);
158
159         if (!hext_stream)
160                 return NULL;
161
162         snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)hext_stream);
163
164         return hext_stream;
165 }
166
167 static void hda_release_hext_stream(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai,
168                                     struct snd_pcm_substream *substream)
169 {
170         struct hdac_ext_stream *hext_stream = hda_get_hext_stream(sdev, cpu_dai, substream);
171         struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
172         struct snd_soc_dai *dai;
173
174         /* only release a stream_tag for the first DAI in the dailink */
175         dai = asoc_rtd_to_cpu(rtd, 0);
176         if (dai == cpu_dai)
177                 snd_hdac_ext_stream_release(hext_stream, HDAC_EXT_STREAM_TYPE_LINK);
178         snd_soc_dai_set_dma_data(cpu_dai, substream, NULL);
179 }
180
181 static void hda_setup_hext_stream(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream,
182                                   unsigned int format_val)
183 {
184         snd_hdac_ext_stream_setup(hext_stream, format_val);
185 }
186
187 static void hda_reset_hext_stream(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream)
188 {
189         snd_hdac_ext_stream_reset(hext_stream);
190 }
191
192 static void hda_codec_dai_set_stream(struct snd_sof_dev *sdev,
193                                      struct snd_pcm_substream *substream,
194                                      struct hdac_stream *hstream)
195 {
196         struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
197         struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
198
199         /* set the hdac_stream in the codec dai */
200         snd_soc_dai_set_stream(codec_dai, hstream, substream->stream);
201 }
202
203 static unsigned int hda_calc_stream_format(struct snd_sof_dev *sdev,
204                                            struct snd_pcm_substream *substream,
205                                            struct snd_pcm_hw_params *params)
206 {
207         struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
208         struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
209         unsigned int link_bps;
210         unsigned int format_val;
211
212         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
213                 link_bps = codec_dai->driver->playback.sig_bits;
214         else
215                 link_bps = codec_dai->driver->capture.sig_bits;
216
217         format_val = snd_hdac_calc_stream_format(params_rate(params), params_channels(params),
218                                                  params_format(params), link_bps, 0);
219
220         dev_dbg(sdev->dev, "format_val=%#x, rate=%d, ch=%d, format=%d\n", format_val,
221                 params_rate(params), params_channels(params), params_format(params));
222
223         return format_val;
224 }
225
226 static struct hdac_ext_link *hda_get_hlink(struct snd_sof_dev *sdev,
227                                            struct snd_pcm_substream *substream)
228 {
229         struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
230         struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
231         struct hdac_bus *bus = sof_to_bus(sdev);
232
233         return snd_hdac_ext_bus_get_hlink_by_name(bus, codec_dai->component->name);
234 }
235
236 static unsigned int generic_calc_stream_format(struct snd_sof_dev *sdev,
237                                                struct snd_pcm_substream *substream,
238                                                struct snd_pcm_hw_params *params)
239 {
240         unsigned int format_val;
241
242         format_val = snd_hdac_calc_stream_format(params_rate(params), params_channels(params),
243                                                  params_format(params),
244                                                  params_physical_width(params),
245                                                  0);
246
247         dev_dbg(sdev->dev, "format_val=%#x, rate=%d, ch=%d, format=%d\n", format_val,
248                 params_rate(params), params_channels(params), params_format(params));
249
250         return format_val;
251 }
252
253 static unsigned int dmic_calc_stream_format(struct snd_sof_dev *sdev,
254                                             struct snd_pcm_substream *substream,
255                                             struct snd_pcm_hw_params *params)
256 {
257         unsigned int format_val;
258         snd_pcm_format_t format;
259         unsigned int channels;
260         unsigned int width;
261
262         channels = params_channels(params);
263         format = params_format(params);
264         width = params_physical_width(params);
265
266         if (format == SNDRV_PCM_FORMAT_S16_LE) {
267                 format = SNDRV_PCM_FORMAT_S32_LE;
268                 channels /= 2;
269                 width = 32;
270         }
271
272         format_val = snd_hdac_calc_stream_format(params_rate(params), channels,
273                                                  format,
274                                                  width,
275                                                  0);
276
277         dev_dbg(sdev->dev, "format_val=%#x, rate=%d, ch=%d, format=%d\n", format_val,
278                 params_rate(params), channels, format);
279
280         return format_val;
281 }
282
283 static struct hdac_ext_link *ssp_get_hlink(struct snd_sof_dev *sdev,
284                                            struct snd_pcm_substream *substream)
285 {
286         struct hdac_bus *bus = sof_to_bus(sdev);
287
288         return hdac_bus_eml_ssp_get_hlink(bus);
289 }
290
291 static struct hdac_ext_link *dmic_get_hlink(struct snd_sof_dev *sdev,
292                                             struct snd_pcm_substream *substream)
293 {
294         struct hdac_bus *bus = sof_to_bus(sdev);
295
296         return hdac_bus_eml_dmic_get_hlink(bus);
297 }
298
299 static struct hdac_ext_link *sdw_get_hlink(struct snd_sof_dev *sdev,
300                                            struct snd_pcm_substream *substream)
301 {
302         struct hdac_bus *bus = sof_to_bus(sdev);
303
304         return hdac_bus_eml_sdw_get_hlink(bus);
305 }
306
307 static int hda_ipc4_pre_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai,
308                                 struct snd_pcm_substream *substream, int cmd)
309 {
310         struct sof_ipc4_fw_data *ipc4_data = sdev->private;
311         struct snd_sof_widget *pipe_widget;
312         struct sof_ipc4_pipeline *pipeline;
313         struct snd_sof_widget *swidget;
314         struct snd_soc_dapm_widget *w;
315         int ret = 0;
316
317         w = snd_soc_dai_get_widget(cpu_dai, substream->stream);
318         swidget = w->dobj.private;
319         pipe_widget = swidget->spipe->pipe_widget;
320         pipeline = pipe_widget->private;
321
322         if (pipe_widget->instance_id < 0)
323                 return 0;
324
325         mutex_lock(&ipc4_data->pipeline_state_mutex);
326
327         switch (cmd) {
328         case SNDRV_PCM_TRIGGER_START:
329         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
330                 break;
331         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
332         case SNDRV_PCM_TRIGGER_SUSPEND:
333         case SNDRV_PCM_TRIGGER_STOP:
334                 ret = sof_ipc4_set_pipeline_state(sdev, pipe_widget->instance_id,
335                                                   SOF_IPC4_PIPE_PAUSED);
336                 if (ret < 0)
337                         goto out;
338
339                 pipeline->state = SOF_IPC4_PIPE_PAUSED;
340                 break;
341         default:
342                 dev_err(sdev->dev, "unknown trigger command %d\n", cmd);
343                 ret = -EINVAL;
344         }
345 out:
346         mutex_unlock(&ipc4_data->pipeline_state_mutex);
347         return ret;
348 }
349
350 static int hda_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai,
351                        struct snd_pcm_substream *substream, int cmd)
352 {
353         struct hdac_ext_stream *hext_stream = snd_soc_dai_get_dma_data(cpu_dai, substream);
354
355         switch (cmd) {
356         case SNDRV_PCM_TRIGGER_START:
357         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
358                 snd_hdac_ext_stream_start(hext_stream);
359                 break;
360         case SNDRV_PCM_TRIGGER_SUSPEND:
361         case SNDRV_PCM_TRIGGER_STOP:
362         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
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;
368         }
369
370         return 0;
371 }
372
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)
375 {
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;
382
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;
387
388         if (pipe_widget->instance_id < 0)
389                 return 0;
390
391         mutex_lock(&ipc4_data->pipeline_state_mutex);
392
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;
401                 }
402
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:
419                 /*
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
422                  */
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;
431         }
432 out:
433         mutex_unlock(&ipc4_data->pipeline_state_mutex);
434         return ret;
435 }
436
437 static struct hdac_ext_stream *sdw_hda_ipc4_get_hext_stream(struct snd_sof_dev *sdev,
438                                                             struct snd_soc_dai *cpu_dai,
439                                                             struct snd_pcm_substream *substream)
440 {
441         struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream);
442         struct snd_sof_widget *swidget = w->dobj.private;
443         struct snd_sof_dai *dai = swidget->private;
444         struct sof_ipc4_copier *ipc4_copier = dai->private;
445         struct sof_ipc4_alh_configuration_blob *blob;
446
447         blob = (struct sof_ipc4_alh_configuration_blob *)ipc4_copier->copier_config;
448
449         /*
450          * Starting with ACE_2_0, re-setting the device_count is mandatory to avoid using
451          * the multi-gateway firmware configuration. The DMA hardware can take care of
452          * multiple links without needing any firmware assistance
453          */
454         blob->alh_cfg.device_count = 1;
455
456         return hda_ipc4_get_hext_stream(sdev, cpu_dai, substream);
457 }
458
459 static const struct hda_dai_widget_dma_ops hda_ipc4_dma_ops = {
460         .get_hext_stream = hda_ipc4_get_hext_stream,
461         .assign_hext_stream = hda_assign_hext_stream,
462         .release_hext_stream = hda_release_hext_stream,
463         .setup_hext_stream = hda_setup_hext_stream,
464         .reset_hext_stream = hda_reset_hext_stream,
465         .pre_trigger = hda_ipc4_pre_trigger,
466         .trigger = hda_trigger,
467         .post_trigger = hda_ipc4_post_trigger,
468         .codec_dai_set_stream = hda_codec_dai_set_stream,
469         .calc_stream_format = hda_calc_stream_format,
470         .get_hlink = hda_get_hlink,
471 };
472
473 static const struct hda_dai_widget_dma_ops ssp_ipc4_dma_ops = {
474         .get_hext_stream = hda_ipc4_get_hext_stream,
475         .assign_hext_stream = hda_assign_hext_stream,
476         .release_hext_stream = hda_release_hext_stream,
477         .setup_hext_stream = hda_setup_hext_stream,
478         .reset_hext_stream = hda_reset_hext_stream,
479         .pre_trigger = hda_ipc4_pre_trigger,
480         .trigger = hda_trigger,
481         .post_trigger = hda_ipc4_post_trigger,
482         .calc_stream_format = generic_calc_stream_format,
483         .get_hlink = ssp_get_hlink,
484 };
485
486 static const struct hda_dai_widget_dma_ops dmic_ipc4_dma_ops = {
487         .get_hext_stream = hda_ipc4_get_hext_stream,
488         .assign_hext_stream = hda_assign_hext_stream,
489         .release_hext_stream = hda_release_hext_stream,
490         .setup_hext_stream = hda_setup_hext_stream,
491         .reset_hext_stream = hda_reset_hext_stream,
492         .pre_trigger = hda_ipc4_pre_trigger,
493         .trigger = hda_trigger,
494         .post_trigger = hda_ipc4_post_trigger,
495         .calc_stream_format = dmic_calc_stream_format,
496         .get_hlink = dmic_get_hlink,
497 };
498
499 static const struct hda_dai_widget_dma_ops sdw_ipc4_dma_ops = {
500         .get_hext_stream = sdw_hda_ipc4_get_hext_stream,
501         .assign_hext_stream = hda_assign_hext_stream,
502         .release_hext_stream = hda_release_hext_stream,
503         .setup_hext_stream = hda_setup_hext_stream,
504         .reset_hext_stream = hda_reset_hext_stream,
505         .pre_trigger = hda_ipc4_pre_trigger,
506         .trigger = hda_trigger,
507         .post_trigger = hda_ipc4_post_trigger,
508         .calc_stream_format = generic_calc_stream_format,
509         .get_hlink = sdw_get_hlink,
510 };
511
512 static const struct hda_dai_widget_dma_ops hda_ipc4_chain_dma_ops = {
513         .get_hext_stream = hda_get_hext_stream,
514         .assign_hext_stream = hda_assign_hext_stream,
515         .release_hext_stream = hda_release_hext_stream,
516         .setup_hext_stream = hda_setup_hext_stream,
517         .reset_hext_stream = hda_reset_hext_stream,
518         .trigger = hda_trigger,
519         .codec_dai_set_stream = hda_codec_dai_set_stream,
520         .calc_stream_format = hda_calc_stream_format,
521         .get_hlink = hda_get_hlink,
522 };
523
524 static int hda_ipc3_post_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai,
525                                  struct snd_pcm_substream *substream, int cmd)
526 {
527         struct hdac_ext_stream *hext_stream = hda_get_hext_stream(sdev, cpu_dai, substream);
528         struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream);
529
530         switch (cmd) {
531         case SNDRV_PCM_TRIGGER_SUSPEND:
532         case SNDRV_PCM_TRIGGER_STOP:
533         {
534                 struct snd_sof_dai_config_data data = { 0 };
535                 int ret;
536
537                 data.dai_data = DMA_CHAN_INVALID;
538                 ret = hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_HW_FREE, &data);
539                 if (ret < 0)
540                         return ret;
541
542                 if (cmd == SNDRV_PCM_TRIGGER_STOP)
543                         return hda_link_dma_cleanup(substream, hext_stream, cpu_dai);
544
545                 break;
546         }
547         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
548                 return hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_PAUSE, NULL);
549         default:
550                 break;
551         }
552
553         return 0;
554 }
555
556 static const struct hda_dai_widget_dma_ops hda_ipc3_dma_ops = {
557         .get_hext_stream = hda_get_hext_stream,
558         .assign_hext_stream = hda_assign_hext_stream,
559         .release_hext_stream = hda_release_hext_stream,
560         .setup_hext_stream = hda_setup_hext_stream,
561         .reset_hext_stream = hda_reset_hext_stream,
562         .trigger = hda_trigger,
563         .post_trigger = hda_ipc3_post_trigger,
564         .codec_dai_set_stream = hda_codec_dai_set_stream,
565         .calc_stream_format = hda_calc_stream_format,
566         .get_hlink = hda_get_hlink,
567 };
568
569 static struct hdac_ext_stream *
570 hda_dspless_get_hext_stream(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai,
571                             struct snd_pcm_substream *substream)
572 {
573         struct hdac_stream *hstream = substream->runtime->private_data;
574
575         return stream_to_hdac_ext_stream(hstream);
576 }
577
578 static void hda_dspless_setup_hext_stream(struct snd_sof_dev *sdev,
579                                           struct hdac_ext_stream *hext_stream,
580                                           unsigned int format_val)
581 {
582         /*
583          * Save the format_val which was adjusted by the maxbps of the codec.
584          * This information is not available on the FE side since there we are
585          * using dummy_codec.
586          */
587         hext_stream->hstream.format_val = format_val;
588 }
589
590 static const struct hda_dai_widget_dma_ops hda_dspless_dma_ops = {
591         .get_hext_stream = hda_dspless_get_hext_stream,
592         .setup_hext_stream = hda_dspless_setup_hext_stream,
593         .codec_dai_set_stream = hda_codec_dai_set_stream,
594         .calc_stream_format = hda_calc_stream_format,
595         .get_hlink = hda_get_hlink,
596 };
597
598 #endif
599
600 const struct hda_dai_widget_dma_ops *
601 hda_select_dai_widget_ops(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget)
602 {
603 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_LINK)
604         struct snd_sof_dai *sdai;
605
606         if (sdev->dspless_mode_selected)
607                 return &hda_dspless_dma_ops;
608
609         sdai = swidget->private;
610
611         switch (sdev->pdata->ipc_type) {
612         case SOF_IPC:
613         {
614                 struct sof_dai_private_data *private = sdai->private;
615
616                 if (private->dai_config->type == SOF_DAI_INTEL_HDA)
617                         return &hda_ipc3_dma_ops;
618                 break;
619         }
620         case SOF_INTEL_IPC4:
621         {
622                 struct sof_ipc4_copier *ipc4_copier = sdai->private;
623                 const struct sof_intel_dsp_desc *chip;
624
625                 chip = get_chip_info(sdev->pdata);
626
627                 switch (ipc4_copier->dai_type) {
628                 case SOF_DAI_INTEL_HDA:
629                 {
630                         struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget;
631                         struct sof_ipc4_pipeline *pipeline = pipe_widget->private;
632
633                         if (pipeline->use_chain_dma)
634                                 return &hda_ipc4_chain_dma_ops;
635
636                         return &hda_ipc4_dma_ops;
637                 }
638                 case SOF_DAI_INTEL_SSP:
639                         if (chip->hw_ip_version < SOF_INTEL_ACE_2_0)
640                                 return NULL;
641                         return &ssp_ipc4_dma_ops;
642                 case SOF_DAI_INTEL_DMIC:
643                         if (chip->hw_ip_version < SOF_INTEL_ACE_2_0)
644                                 return NULL;
645                         return &dmic_ipc4_dma_ops;
646                 case SOF_DAI_INTEL_ALH:
647                         if (chip->hw_ip_version < SOF_INTEL_ACE_2_0)
648                                 return NULL;
649                         return &sdw_ipc4_dma_ops;
650
651                 default:
652                         break;
653                 }
654                 break;
655         }
656         default:
657                 break;
658         }
659 #endif
660         return NULL;
661 }