]> Git Repo - linux.git/blob - sound/soc/sof/intel/hda-dai-ops.c
Linux 6.14-rc3
[linux.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
7
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"
19
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)
22 /*
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.
26  */
27 static bool hda_check_fes(struct snd_soc_pcm_runtime *rtd,
28                           int dir, int stream_tag)
29 {
30         struct snd_pcm_substream *fe_substream;
31         struct hdac_stream *fe_hstream;
32         struct snd_soc_dpcm *dpcm;
33
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;
39         }
40
41         return false;
42 }
43
44 static struct hdac_ext_stream *
45 hda_link_stream_assign(struct hdac_bus *bus, struct snd_pcm_substream *substream)
46 {
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;
53
54         int stream_dir = substream->stream;
55
56         if (!bus->ppcap) {
57                 dev_err(bus->dev, "stream type not supported\n");
58                 return NULL;
59         }
60
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;
67
68                 hda_stream = hstream_to_sof_hda_stream(hext_stream);
69                 sdev = hda_stream->sdev;
70                 chip = get_chip_info(sdev->pdata);
71
72                 /* check if link is available */
73                 if (!hext_stream->link_locked) {
74                         /*
75                          * choose the first available link for platforms that do not have the
76                          * PROCEN_FMT_QUIRK set.
77                          */
78                         if (!(chip->quirks & SOF_INTEL_PROCEN_FMT_QUIRK)) {
79                                 res = hext_stream;
80                                 break;
81                         }
82
83                         if (hstream->opened) {
84                                 /*
85                                  * check if the stream tag matches the stream
86                                  * tag of one of the connected FEs
87                                  */
88                                 if (hda_check_fes(rtd, stream_dir,
89                                                   hstream->stream_tag)) {
90                                         res = hext_stream;
91                                         break;
92                                 }
93                         } else {
94                                 res = hext_stream;
95
96                                 /*
97                                  * This must be a hostless stream.
98                                  * So reserve the host DMA channel.
99                                  */
100                                 hda_stream->host_reserved = 1;
101                                 break;
102                         }
103                 }
104         }
105
106         if (res) {
107                 /* Make sure that host and link DMA is decoupled. */
108                 snd_hdac_ext_stream_decouple_locked(bus, res, true);
109
110                 res->link_locked = 1;
111                 res->link_substream = substream;
112         }
113         spin_unlock_irq(&bus->reg_lock);
114
115         return res;
116 }
117
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)
121 {
122         return snd_soc_dai_get_dma_data(cpu_dai, substream);
123 }
124
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)
128 {
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;
133
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;
138
139         /* mark pipeline so that it can be skipped during FE trigger */
140         pipeline->skip_during_fe_trigger = true;
141
142         return snd_soc_dai_get_dma_data(cpu_dai, substream);
143 }
144
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)
148 {
149         struct hdac_ext_stream *hext_stream;
150
151         hext_stream = hda_link_stream_assign(sof_to_bus(sdev), substream);
152         if (!hext_stream)
153                 return NULL;
154
155         snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)hext_stream);
156
157         return hext_stream;
158 }
159
160 static void hda_release_hext_stream(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai,
161                                     struct snd_pcm_substream *substream)
162 {
163         struct hdac_ext_stream *hext_stream = hda_get_hext_stream(sdev, cpu_dai, substream);
164
165         snd_soc_dai_set_dma_data(cpu_dai, substream, NULL);
166         snd_hdac_ext_stream_release(hext_stream, HDAC_EXT_STREAM_TYPE_LINK);
167 }
168
169 static void hda_setup_hext_stream(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream,
170                                   unsigned int format_val)
171 {
172         snd_hdac_ext_stream_setup(hext_stream, format_val);
173 }
174
175 static void hda_reset_hext_stream(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream)
176 {
177         snd_hdac_ext_stream_reset(hext_stream);
178 }
179
180 static void hda_codec_dai_set_stream(struct snd_sof_dev *sdev,
181                                      struct snd_pcm_substream *substream,
182                                      struct hdac_stream *hstream)
183 {
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);
186
187         /* set the hdac_stream in the codec dai */
188         snd_soc_dai_set_stream(codec_dai, hstream, substream->stream);
189 }
190
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)
194 {
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;
200
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;
205
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));
209
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));
212
213         return format_val;
214 }
215
216 static struct hdac_ext_link *hda_get_hlink(struct snd_sof_dev *sdev,
217                                            struct snd_pcm_substream *substream)
218 {
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);
222
223         return snd_hdac_ext_bus_get_hlink_by_name(bus, codec_dai->component->name);
224 }
225
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)
229 {
230         unsigned int format_val;
231         unsigned int bits;
232
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));
236
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));
239
240         return format_val;
241 }
242
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)
246 {
247         unsigned int format_val;
248         snd_pcm_format_t format;
249         unsigned int channels;
250         unsigned int width;
251         unsigned int bits;
252
253         channels = params_channels(params);
254         format = params_format(params);
255         width = params_physical_width(params);
256
257         if (format == SNDRV_PCM_FORMAT_S16_LE) {
258                 format = SNDRV_PCM_FORMAT_S32_LE;
259                 channels /= 2;
260                 width = 32;
261         }
262
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));
265
266         dev_dbg(sdev->dev, "format_val=%#x, rate=%d, ch=%d, format=%d\n", format_val,
267                 params_rate(params), channels, format);
268
269         return format_val;
270 }
271
272 static struct hdac_ext_link *ssp_get_hlink(struct snd_sof_dev *sdev,
273                                            struct snd_pcm_substream *substream)
274 {
275         struct hdac_bus *bus = sof_to_bus(sdev);
276
277         return hdac_bus_eml_ssp_get_hlink(bus);
278 }
279
280 static struct hdac_ext_link *dmic_get_hlink(struct snd_sof_dev *sdev,
281                                             struct snd_pcm_substream *substream)
282 {
283         struct hdac_bus *bus = sof_to_bus(sdev);
284
285         return hdac_bus_eml_dmic_get_hlink(bus);
286 }
287
288 static struct hdac_ext_link *sdw_get_hlink(struct snd_sof_dev *sdev,
289                                            struct snd_pcm_substream *substream)
290 {
291         struct hdac_bus *bus = sof_to_bus(sdev);
292
293         return hdac_bus_eml_sdw_get_hlink(bus);
294 }
295
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)
298 {
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;
305
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;
310
311         if (pipe_widget->instance_id < 0)
312                 return 0;
313
314         mutex_lock(&ipc4_data->pipeline_state_mutex);
315
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;
327
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;
333         }
334 out:
335         mutex_unlock(&ipc4_data->pipeline_state_mutex);
336         return ret;
337 }
338
339 static int hda_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai,
340                        struct snd_pcm_substream *substream, int cmd)
341 {
342         struct hdac_ext_stream *hext_stream = snd_soc_dai_get_dma_data(cpu_dai, substream);
343
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:
350                 /*
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.
354                  */
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;
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 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,
449 };
450
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,
462 };
463
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,
475 };
476
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,
488 };
489
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,
500 };
501
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,
511 };
512
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)
515 {
516         struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream);
517
518         switch (cmd) {
519         case SNDRV_PCM_TRIGGER_SUSPEND:
520         case SNDRV_PCM_TRIGGER_STOP:
521         {
522                 struct snd_sof_dai_config_data data = { 0 };
523                 int ret;
524
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;
529
530                 break;
531         }
532         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
533                 return hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_PAUSE, NULL);
534         default:
535                 break;
536         }
537
538         return 0;
539 }
540
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,
552 };
553
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)
557 {
558         struct hdac_stream *hstream = substream->runtime->private_data;
559
560         return stream_to_hdac_ext_stream(hstream);
561 }
562
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)
566 {
567         /*
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.
571          */
572         hext_stream->hstream.format_val = format_val;
573 }
574
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,
581 };
582
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,
588 };
589
590 #endif
591
592 const struct hda_dai_widget_dma_ops *
593 hda_select_dai_widget_ops(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget)
594 {
595 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_LINK)
596         struct snd_sof_dai *sdai;
597         const struct sof_intel_dsp_desc *chip;
598
599         chip = get_chip_info(sdev->pdata);
600         sdai = swidget->private;
601
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;
612                 }
613         }
614
615         switch (sdev->pdata->ipc_type) {
616         case SOF_IPC_TYPE_3:
617         {
618                 struct sof_dai_private_data *private = sdai->private;
619
620                 if (private->dai_config->type == SOF_DAI_INTEL_HDA)
621                         return &hda_ipc3_dma_ops;
622                 break;
623         }
624         case SOF_IPC_TYPE_4:
625         {
626                 struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget;
627                 struct sof_ipc4_pipeline *pipeline = pipe_widget->private;
628
629                 switch (sdai->type) {
630                 case SOF_DAI_INTEL_HDA:
631                         if (pipeline->use_chain_dma)
632                                 return &hda_ipc4_chain_dma_ops;
633
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;
649
650                 default:
651                         break;
652                 }
653                 break;
654         }
655         default:
656                 break;
657         }
658 #endif
659         return NULL;
660 }
This page took 0.06897 seconds and 4 git commands to generate.