Merge tag 'powerpc-6.6-6' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc...
[platform/kernel/linux-starfive.git] / sound / soc / sof / sof-audio.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) 2019 Intel Corporation. All rights reserved.
7 //
8 // Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
9 //
10
11 #include <linux/bitfield.h>
12 #include <trace/events/sof.h>
13 #include "sof-audio.h"
14 #include "sof-of-dev.h"
15 #include "ops.h"
16
17 static bool is_virtual_widget(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *widget,
18                               const char *func)
19 {
20         switch (widget->id) {
21         case snd_soc_dapm_out_drv:
22         case snd_soc_dapm_output:
23         case snd_soc_dapm_input:
24                 dev_dbg(sdev->dev, "%s: %s is a virtual widget\n", func, widget->name);
25                 return true;
26         default:
27                 return false;
28         }
29 }
30
31 static void sof_reset_route_setup_status(struct snd_sof_dev *sdev, struct snd_sof_widget *widget)
32 {
33         const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
34         struct snd_sof_route *sroute;
35
36         list_for_each_entry(sroute, &sdev->route_list, list)
37                 if (sroute->src_widget == widget || sroute->sink_widget == widget) {
38                         if (sroute->setup && tplg_ops && tplg_ops->route_free)
39                                 tplg_ops->route_free(sdev, sroute);
40
41                         sroute->setup = false;
42                 }
43 }
44
45 static int sof_widget_free_unlocked(struct snd_sof_dev *sdev,
46                                     struct snd_sof_widget *swidget)
47 {
48         const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
49         struct snd_sof_widget *pipe_widget;
50         int err = 0;
51         int ret;
52
53         if (!swidget->private)
54                 return 0;
55
56         trace_sof_widget_free(swidget);
57
58         /* only free when use_count is 0 */
59         if (--swidget->use_count)
60                 return 0;
61
62         pipe_widget = swidget->spipe->pipe_widget;
63
64         /* reset route setup status for all routes that contain this widget */
65         sof_reset_route_setup_status(sdev, swidget);
66
67         /* free DAI config and continue to free widget even if it fails */
68         if (WIDGET_IS_DAI(swidget->id)) {
69                 struct snd_sof_dai_config_data data;
70                 unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_FREE;
71
72                 data.dai_data = DMA_CHAN_INVALID;
73
74                 if (tplg_ops && tplg_ops->dai_config) {
75                         err = tplg_ops->dai_config(sdev, swidget, flags, &data);
76                         if (err < 0)
77                                 dev_err(sdev->dev, "failed to free config for widget %s\n",
78                                         swidget->widget->name);
79                 }
80         }
81
82         /* continue to disable core even if IPC fails */
83         if (tplg_ops && tplg_ops->widget_free) {
84                 ret = tplg_ops->widget_free(sdev, swidget);
85                 if (ret < 0 && !err)
86                         err = ret;
87         }
88
89         /*
90          * disable widget core. continue to route setup status and complete flag
91          * even if this fails and return the appropriate error
92          */
93         ret = snd_sof_dsp_core_put(sdev, swidget->core);
94         if (ret < 0) {
95                 dev_err(sdev->dev, "error: failed to disable target core: %d for widget %s\n",
96                         swidget->core, swidget->widget->name);
97                 if (!err)
98                         err = ret;
99         }
100
101         /*
102          * free the scheduler widget (same as pipe_widget) associated with the current swidget.
103          * skip for static pipelines
104          */
105         if (swidget->dynamic_pipeline_widget && swidget->id != snd_soc_dapm_scheduler) {
106                 ret = sof_widget_free_unlocked(sdev, pipe_widget);
107                 if (ret < 0 && !err)
108                         err = ret;
109         }
110
111         /* clear pipeline complete */
112         if (swidget->id == snd_soc_dapm_scheduler)
113                 swidget->spipe->complete = 0;
114
115         if (!err)
116                 dev_dbg(sdev->dev, "widget %s freed\n", swidget->widget->name);
117
118         return err;
119 }
120
121 int sof_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget)
122 {
123         int ret;
124
125         mutex_lock(&swidget->setup_mutex);
126         ret = sof_widget_free_unlocked(sdev, swidget);
127         mutex_unlock(&swidget->setup_mutex);
128
129         return ret;
130 }
131 EXPORT_SYMBOL(sof_widget_free);
132
133 static int sof_widget_setup_unlocked(struct snd_sof_dev *sdev,
134                                      struct snd_sof_widget *swidget)
135 {
136         const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
137         bool use_count_decremented = false;
138         int ret;
139
140         /* skip if there is no private data */
141         if (!swidget->private)
142                 return 0;
143
144         trace_sof_widget_setup(swidget);
145
146         /* widget already set up */
147         if (++swidget->use_count > 1)
148                 return 0;
149
150         /*
151          * The scheduler widget for a pipeline is not part of the connected DAPM
152          * widget list and it needs to be set up before the widgets in the pipeline
153          * are set up. The use_count for the scheduler widget is incremented for every
154          * widget in a given pipeline to ensure that it is freed only after the last
155          * widget in the pipeline is freed. Skip setting up scheduler widget for static pipelines.
156          */
157         if (swidget->dynamic_pipeline_widget && swidget->id != snd_soc_dapm_scheduler) {
158                 if (!swidget->spipe || !swidget->spipe->pipe_widget) {
159                         dev_err(sdev->dev, "No pipeline set for %s\n", swidget->widget->name);
160                         ret = -EINVAL;
161                         goto use_count_dec;
162                 }
163
164                 ret = sof_widget_setup_unlocked(sdev, swidget->spipe->pipe_widget);
165                 if (ret < 0)
166                         goto use_count_dec;
167         }
168
169         /* enable widget core */
170         ret = snd_sof_dsp_core_get(sdev, swidget->core);
171         if (ret < 0) {
172                 dev_err(sdev->dev, "error: failed to enable target core for widget %s\n",
173                         swidget->widget->name);
174                 goto pipe_widget_free;
175         }
176
177         /* setup widget in the DSP */
178         if (tplg_ops && tplg_ops->widget_setup) {
179                 ret = tplg_ops->widget_setup(sdev, swidget);
180                 if (ret < 0)
181                         goto core_put;
182         }
183
184         /* send config for DAI components */
185         if (WIDGET_IS_DAI(swidget->id)) {
186                 unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS;
187
188                 /*
189                  * The config flags saved during BE DAI hw_params will be used for IPC3. IPC4 does
190                  * not use the flags argument.
191                  */
192                 if (tplg_ops && tplg_ops->dai_config) {
193                         ret = tplg_ops->dai_config(sdev, swidget, flags, NULL);
194                         if (ret < 0)
195                                 goto widget_free;
196                 }
197         }
198
199         /* restore kcontrols for widget */
200         if (tplg_ops && tplg_ops->control && tplg_ops->control->widget_kcontrol_setup) {
201                 ret = tplg_ops->control->widget_kcontrol_setup(sdev, swidget);
202                 if (ret < 0)
203                         goto widget_free;
204         }
205
206         dev_dbg(sdev->dev, "widget %s setup complete\n", swidget->widget->name);
207
208         return 0;
209
210 widget_free:
211         /* widget use_count and core ref_count will both be decremented by sof_widget_free() */
212         sof_widget_free_unlocked(sdev, swidget);
213         use_count_decremented = true;
214 core_put:
215         if (!use_count_decremented)
216                 snd_sof_dsp_core_put(sdev, swidget->core);
217 pipe_widget_free:
218         if (swidget->id != snd_soc_dapm_scheduler)
219                 sof_widget_free_unlocked(sdev, swidget->spipe->pipe_widget);
220 use_count_dec:
221         if (!use_count_decremented)
222                 swidget->use_count--;
223
224         return ret;
225 }
226
227 int sof_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget)
228 {
229         int ret;
230
231         mutex_lock(&swidget->setup_mutex);
232         ret = sof_widget_setup_unlocked(sdev, swidget);
233         mutex_unlock(&swidget->setup_mutex);
234
235         return ret;
236 }
237 EXPORT_SYMBOL(sof_widget_setup);
238
239 int sof_route_setup(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *wsource,
240                     struct snd_soc_dapm_widget *wsink)
241 {
242         const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
243         struct snd_sof_widget *src_widget = wsource->dobj.private;
244         struct snd_sof_widget *sink_widget = wsink->dobj.private;
245         struct snd_sof_route *sroute;
246         bool route_found = false;
247
248         /* ignore routes involving virtual widgets in topology */
249         if (is_virtual_widget(sdev, src_widget->widget, __func__) ||
250             is_virtual_widget(sdev, sink_widget->widget, __func__))
251                 return 0;
252
253         /* find route matching source and sink widgets */
254         list_for_each_entry(sroute, &sdev->route_list, list)
255                 if (sroute->src_widget == src_widget && sroute->sink_widget == sink_widget) {
256                         route_found = true;
257                         break;
258                 }
259
260         if (!route_found) {
261                 dev_err(sdev->dev, "error: cannot find SOF route for source %s -> %s sink\n",
262                         wsource->name, wsink->name);
263                 return -EINVAL;
264         }
265
266         /* nothing to do if route is already set up */
267         if (sroute->setup)
268                 return 0;
269
270         if (tplg_ops && tplg_ops->route_setup) {
271                 int ret = tplg_ops->route_setup(sdev, sroute);
272
273                 if (ret < 0)
274                         return ret;
275         }
276
277         sroute->setup = true;
278         return 0;
279 }
280
281 static int sof_setup_pipeline_connections(struct snd_sof_dev *sdev,
282                                           struct snd_soc_dapm_widget_list *list, int dir)
283 {
284         const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
285         struct snd_soc_dapm_widget *widget;
286         struct snd_sof_route *sroute;
287         struct snd_soc_dapm_path *p;
288         int ret = 0;
289         int i;
290
291         /*
292          * Set up connections between widgets in the sink/source paths based on direction.
293          * Some non-SOF widgets exist in topology either for compatibility or for the
294          * purpose of connecting a pipeline from a host to a DAI in order to receive the DAPM
295          * events. But they are not handled by the firmware. So ignore them.
296          */
297         if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
298                 for_each_dapm_widgets(list, i, widget) {
299                         if (!widget->dobj.private)
300                                 continue;
301
302                         snd_soc_dapm_widget_for_each_sink_path(widget, p) {
303                                 if (!widget_in_list(list, p->sink))
304                                         continue;
305
306                                 if (p->sink->dobj.private) {
307                                         ret = sof_route_setup(sdev, widget, p->sink);
308                                         if (ret < 0)
309                                                 return ret;
310                                 }
311                         }
312                 }
313         } else {
314                 for_each_dapm_widgets(list, i, widget) {
315                         if (!widget->dobj.private)
316                                 continue;
317
318                         snd_soc_dapm_widget_for_each_source_path(widget, p) {
319                                 if (!widget_in_list(list, p->source))
320                                         continue;
321
322                                 if (p->source->dobj.private) {
323                                         ret = sof_route_setup(sdev, p->source, widget);
324                                         if (ret < 0)
325                                                 return ret;
326                                 }
327                         }
328                 }
329         }
330
331         /*
332          * The above loop handles connections between widgets that belong to the DAPM widget list.
333          * This is not sufficient to handle loopback cases between pipelines configured with
334          * different directions, e.g. a sidetone or an amplifier feedback connected to a speaker
335          * protection module.
336          */
337         list_for_each_entry(sroute, &sdev->route_list, list) {
338                 bool src_widget_in_dapm_list, sink_widget_in_dapm_list;
339                 struct snd_sof_widget *swidget;
340
341                 if (sroute->setup)
342                         continue;
343
344                 src_widget_in_dapm_list = widget_in_list(list, sroute->src_widget->widget);
345                 sink_widget_in_dapm_list = widget_in_list(list, sroute->sink_widget->widget);
346
347                 /*
348                  * if both source and sink are in the DAPM list, the route must already have been
349                  * set up above. And if neither are in the DAPM list, the route shouldn't be
350                  * handled now.
351                  */
352                 if (src_widget_in_dapm_list == sink_widget_in_dapm_list)
353                         continue;
354
355                 /*
356                  * At this point either the source widget or the sink widget is in the DAPM list
357                  * with a route that might need to be set up. Check the use_count of the widget
358                  * that is not in the DAPM list to confirm if it is in use currently before setting
359                  * up the route.
360                  */
361                 if (src_widget_in_dapm_list)
362                         swidget = sroute->sink_widget;
363                 else
364                         swidget = sroute->src_widget;
365
366                 mutex_lock(&swidget->setup_mutex);
367                 if (!swidget->use_count) {
368                         mutex_unlock(&swidget->setup_mutex);
369                         continue;
370                 }
371
372                 if (tplg_ops && tplg_ops->route_setup) {
373                         /*
374                          * this route will get freed when either the source widget or the sink
375                          * widget is freed during hw_free
376                          */
377                         ret = tplg_ops->route_setup(sdev, sroute);
378                         if (!ret)
379                                 sroute->setup = true;
380                 }
381
382                 mutex_unlock(&swidget->setup_mutex);
383
384                 if (ret < 0)
385                         return ret;
386         }
387
388         return 0;
389 }
390
391 static void
392 sof_unprepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *widget,
393                               struct snd_soc_dapm_widget_list *list)
394 {
395         const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
396         struct snd_sof_widget *swidget = widget->dobj.private;
397         const struct sof_ipc_tplg_widget_ops *widget_ops;
398         struct snd_soc_dapm_path *p;
399
400         if (is_virtual_widget(sdev, widget, __func__))
401                 return;
402
403         /* skip if the widget is in use or if it is already unprepared */
404         if (!swidget || !swidget->prepared || swidget->use_count > 0)
405                 goto sink_unprepare;
406
407         widget_ops = tplg_ops ? tplg_ops->widget : NULL;
408         if (widget_ops && widget_ops[widget->id].ipc_unprepare)
409                 /* unprepare the source widget */
410                 widget_ops[widget->id].ipc_unprepare(swidget);
411
412         swidget->prepared = false;
413
414 sink_unprepare:
415         /* unprepare all widgets in the sink paths */
416         snd_soc_dapm_widget_for_each_sink_path(widget, p) {
417                 if (!widget_in_list(list, p->sink))
418                         continue;
419                 if (!p->walking && p->sink->dobj.private) {
420                         p->walking = true;
421                         sof_unprepare_widgets_in_path(sdev, p->sink, list);
422                         p->walking = false;
423                 }
424         }
425 }
426
427 static int
428 sof_prepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *widget,
429                             struct snd_pcm_hw_params *fe_params,
430                             struct snd_sof_platform_stream_params *platform_params,
431                             struct snd_pcm_hw_params *pipeline_params, int dir,
432                             struct snd_soc_dapm_widget_list *list)
433 {
434         const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
435         struct snd_sof_widget *swidget = widget->dobj.private;
436         const struct sof_ipc_tplg_widget_ops *widget_ops;
437         struct snd_soc_dapm_path *p;
438         int ret;
439
440         if (is_virtual_widget(sdev, widget, __func__))
441                 return 0;
442
443         widget_ops = tplg_ops ? tplg_ops->widget : NULL;
444         if (!widget_ops)
445                 return 0;
446
447         if (!swidget || !widget_ops[widget->id].ipc_prepare || swidget->prepared)
448                 goto sink_prepare;
449
450         /* prepare the source widget */
451         ret = widget_ops[widget->id].ipc_prepare(swidget, fe_params, platform_params,
452                                              pipeline_params, dir);
453         if (ret < 0) {
454                 dev_err(sdev->dev, "failed to prepare widget %s\n", widget->name);
455                 return ret;
456         }
457
458         swidget->prepared = true;
459
460 sink_prepare:
461         /* prepare all widgets in the sink paths */
462         snd_soc_dapm_widget_for_each_sink_path(widget, p) {
463                 if (!widget_in_list(list, p->sink))
464                         continue;
465                 if (!p->walking && p->sink->dobj.private) {
466                         p->walking = true;
467                         ret = sof_prepare_widgets_in_path(sdev, p->sink,  fe_params,
468                                                           platform_params, pipeline_params, dir,
469                                                           list);
470                         p->walking = false;
471                         if (ret < 0) {
472                                 /* unprepare the source widget */
473                                 if (widget_ops[widget->id].ipc_unprepare &&
474                                     swidget && swidget->prepared) {
475                                         widget_ops[widget->id].ipc_unprepare(swidget);
476                                         swidget->prepared = false;
477                                 }
478                                 return ret;
479                         }
480                 }
481         }
482
483         return 0;
484 }
485
486 /*
487  * free all widgets in the sink path starting from the source widget
488  * (DAI type for capture, AIF type for playback)
489  */
490 static int sof_free_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *widget,
491                                     int dir, struct snd_sof_pcm *spcm)
492 {
493         struct snd_soc_dapm_widget_list *list = spcm->stream[dir].list;
494         struct snd_soc_dapm_path *p;
495         int err;
496         int ret = 0;
497
498         if (is_virtual_widget(sdev, widget, __func__))
499                 return 0;
500
501         if (widget->dobj.private) {
502                 err = sof_widget_free(sdev, widget->dobj.private);
503                 if (err < 0)
504                         ret = err;
505         }
506
507         /* free all widgets in the sink paths even in case of error to keep use counts balanced */
508         snd_soc_dapm_widget_for_each_sink_path(widget, p) {
509                 if (!p->walking) {
510                         if (!widget_in_list(list, p->sink))
511                                 continue;
512
513                         p->walking = true;
514
515                         err = sof_free_widgets_in_path(sdev, p->sink, dir, spcm);
516                         if (err < 0)
517                                 ret = err;
518                         p->walking = false;
519                 }
520         }
521
522         return ret;
523 }
524
525 /*
526  * set up all widgets in the sink path starting from the source widget
527  * (DAI type for capture, AIF type for playback).
528  * The error path in this function ensures that all successfully set up widgets getting freed.
529  */
530 static int sof_set_up_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *widget,
531                                       int dir, struct snd_sof_pcm *spcm)
532 {
533         struct snd_sof_pcm_stream_pipeline_list *pipeline_list = &spcm->stream[dir].pipeline_list;
534         struct snd_soc_dapm_widget_list *list = spcm->stream[dir].list;
535         struct snd_sof_widget *swidget = widget->dobj.private;
536         struct snd_sof_pipeline *spipe;
537         struct snd_soc_dapm_path *p;
538         int ret;
539
540         if (is_virtual_widget(sdev, widget, __func__))
541                 return 0;
542
543         if (swidget) {
544                 int i;
545
546                 ret = sof_widget_setup(sdev, widget->dobj.private);
547                 if (ret < 0)
548                         return ret;
549
550                 /* skip populating the pipe_widgets array if it is NULL */
551                 if (!pipeline_list->pipelines)
552                         goto sink_setup;
553
554                 /*
555                  * Add the widget's pipe_widget to the list of pipelines to be triggered if not
556                  * already in the list. This will result in the pipelines getting added in the
557                  * order source to sink.
558                  */
559                 for (i = 0; i < pipeline_list->count; i++) {
560                         spipe = pipeline_list->pipelines[i];
561                         if (spipe == swidget->spipe)
562                                 break;
563                 }
564
565                 if (i == pipeline_list->count) {
566                         pipeline_list->count++;
567                         pipeline_list->pipelines[i] = swidget->spipe;
568                 }
569         }
570
571 sink_setup:
572         snd_soc_dapm_widget_for_each_sink_path(widget, p) {
573                 if (!p->walking) {
574                         if (!widget_in_list(list, p->sink))
575                                 continue;
576
577                         p->walking = true;
578
579                         ret = sof_set_up_widgets_in_path(sdev, p->sink, dir, spcm);
580                         p->walking = false;
581                         if (ret < 0) {
582                                 if (swidget)
583                                         sof_widget_free(sdev, swidget);
584                                 return ret;
585                         }
586                 }
587         }
588
589         return 0;
590 }
591
592 static int
593 sof_walk_widgets_in_order(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm,
594                           struct snd_pcm_hw_params *fe_params,
595                           struct snd_sof_platform_stream_params *platform_params, int dir,
596                           enum sof_widget_op op)
597 {
598         struct snd_soc_dapm_widget_list *list = spcm->stream[dir].list;
599         struct snd_soc_dapm_widget *widget;
600         char *str;
601         int ret = 0;
602         int i;
603
604         if (!list)
605                 return 0;
606
607         for_each_dapm_widgets(list, i, widget) {
608                 if (is_virtual_widget(sdev, widget, __func__))
609                         continue;
610
611                 /* starting widget for playback is AIF type */
612                 if (dir == SNDRV_PCM_STREAM_PLAYBACK && widget->id != snd_soc_dapm_aif_in)
613                         continue;
614
615                 /* starting widget for capture is DAI type */
616                 if (dir == SNDRV_PCM_STREAM_CAPTURE && widget->id != snd_soc_dapm_dai_out)
617                         continue;
618
619                 switch (op) {
620                 case SOF_WIDGET_SETUP:
621                         ret = sof_set_up_widgets_in_path(sdev, widget, dir, spcm);
622                         str = "set up";
623                         break;
624                 case SOF_WIDGET_FREE:
625                         ret = sof_free_widgets_in_path(sdev, widget, dir, spcm);
626                         str = "free";
627                         break;
628                 case SOF_WIDGET_PREPARE:
629                 {
630                         struct snd_pcm_hw_params pipeline_params;
631
632                         str = "prepare";
633                         /*
634                          * When walking the list of connected widgets, the pipeline_params for each
635                          * widget is modified by the source widget in the path. Use a local
636                          * copy of the runtime params as the pipeline_params so that the runtime
637                          * params does not get overwritten.
638                          */
639                         memcpy(&pipeline_params, fe_params, sizeof(*fe_params));
640
641                         ret = sof_prepare_widgets_in_path(sdev, widget, fe_params, platform_params,
642                                                           &pipeline_params, dir, list);
643                         break;
644                 }
645                 case SOF_WIDGET_UNPREPARE:
646                         sof_unprepare_widgets_in_path(sdev, widget, list);
647                         break;
648                 default:
649                         dev_err(sdev->dev, "Invalid widget op %d\n", op);
650                         return -EINVAL;
651                 }
652                 if (ret < 0) {
653                         dev_err(sdev->dev, "Failed to %s connected widgets\n", str);
654                         return ret;
655                 }
656         }
657
658         return 0;
659 }
660
661 int sof_widget_list_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm,
662                           struct snd_pcm_hw_params *fe_params,
663                           struct snd_sof_platform_stream_params *platform_params,
664                           int dir)
665 {
666         const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
667         struct snd_soc_dapm_widget_list *list = spcm->stream[dir].list;
668         struct snd_soc_dapm_widget *widget;
669         int i, ret;
670
671         /* nothing to set up */
672         if (!list)
673                 return 0;
674
675         /*
676          * Prepare widgets for set up. The prepare step is used to allocate memory, assign
677          * instance ID and pick the widget configuration based on the runtime PCM params.
678          */
679         ret = sof_walk_widgets_in_order(sdev, spcm, fe_params, platform_params,
680                                         dir, SOF_WIDGET_PREPARE);
681         if (ret < 0)
682                 return ret;
683
684         /* Set up is used to send the IPC to the DSP to create the widget */
685         ret = sof_walk_widgets_in_order(sdev, spcm, fe_params, platform_params,
686                                         dir, SOF_WIDGET_SETUP);
687         if (ret < 0) {
688                 sof_walk_widgets_in_order(sdev, spcm, fe_params, platform_params,
689                                           dir, SOF_WIDGET_UNPREPARE);
690                 return ret;
691         }
692
693         /*
694          * error in setting pipeline connections will result in route status being reset for
695          * routes that were successfully set up when the widgets are freed.
696          */
697         ret = sof_setup_pipeline_connections(sdev, list, dir);
698         if (ret < 0)
699                 goto widget_free;
700
701         /* complete pipelines */
702         for_each_dapm_widgets(list, i, widget) {
703                 struct snd_sof_widget *swidget = widget->dobj.private;
704                 struct snd_sof_widget *pipe_widget;
705                 struct snd_sof_pipeline *spipe;
706
707                 if (!swidget || sdev->dspless_mode_selected)
708                         continue;
709
710                 spipe = swidget->spipe;
711                 if (!spipe) {
712                         dev_err(sdev->dev, "no pipeline found for %s\n",
713                                 swidget->widget->name);
714                         ret = -EINVAL;
715                         goto widget_free;
716                 }
717
718                 pipe_widget = spipe->pipe_widget;
719                 if (!pipe_widget) {
720                         dev_err(sdev->dev, "error: no pipeline widget found for %s\n",
721                                 swidget->widget->name);
722                         ret = -EINVAL;
723                         goto widget_free;
724                 }
725
726                 if (spipe->complete)
727                         continue;
728
729                 if (tplg_ops && tplg_ops->pipeline_complete) {
730                         spipe->complete = tplg_ops->pipeline_complete(sdev, pipe_widget);
731                         if (spipe->complete < 0) {
732                                 ret = spipe->complete;
733                                 goto widget_free;
734                         }
735                 }
736         }
737
738         return 0;
739
740 widget_free:
741         sof_walk_widgets_in_order(sdev, spcm, fe_params, platform_params, dir,
742                                   SOF_WIDGET_FREE);
743         sof_walk_widgets_in_order(sdev, spcm, NULL, NULL, dir, SOF_WIDGET_UNPREPARE);
744
745         return ret;
746 }
747
748 int sof_widget_list_free(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, int dir)
749 {
750         struct snd_sof_pcm_stream_pipeline_list *pipeline_list = &spcm->stream[dir].pipeline_list;
751         struct snd_soc_dapm_widget_list *list = spcm->stream[dir].list;
752         int ret;
753
754         /* nothing to free */
755         if (!list)
756                 return 0;
757
758         /* send IPC to free widget in the DSP */
759         ret = sof_walk_widgets_in_order(sdev, spcm, NULL, NULL, dir, SOF_WIDGET_FREE);
760
761         /* unprepare the widget */
762         sof_walk_widgets_in_order(sdev, spcm, NULL, NULL, dir, SOF_WIDGET_UNPREPARE);
763
764         snd_soc_dapm_dai_free_widgets(&list);
765         spcm->stream[dir].list = NULL;
766
767         pipeline_list->count = 0;
768
769         return ret;
770 }
771
772 /*
773  * helper to determine if there are only D0i3 compatible
774  * streams active
775  */
776 bool snd_sof_dsp_only_d0i3_compatible_stream_active(struct snd_sof_dev *sdev)
777 {
778         struct snd_pcm_substream *substream;
779         struct snd_sof_pcm *spcm;
780         bool d0i3_compatible_active = false;
781         int dir;
782
783         list_for_each_entry(spcm, &sdev->pcm_list, list) {
784                 for_each_pcm_streams(dir) {
785                         substream = spcm->stream[dir].substream;
786                         if (!substream || !substream->runtime)
787                                 continue;
788
789                         /*
790                          * substream->runtime being not NULL indicates
791                          * that the stream is open. No need to check the
792                          * stream state.
793                          */
794                         if (!spcm->stream[dir].d0i3_compatible)
795                                 return false;
796
797                         d0i3_compatible_active = true;
798                 }
799         }
800
801         return d0i3_compatible_active;
802 }
803 EXPORT_SYMBOL(snd_sof_dsp_only_d0i3_compatible_stream_active);
804
805 bool snd_sof_stream_suspend_ignored(struct snd_sof_dev *sdev)
806 {
807         struct snd_sof_pcm *spcm;
808
809         list_for_each_entry(spcm, &sdev->pcm_list, list) {
810                 if (spcm->stream[SNDRV_PCM_STREAM_PLAYBACK].suspend_ignored ||
811                     spcm->stream[SNDRV_PCM_STREAM_CAPTURE].suspend_ignored)
812                         return true;
813         }
814
815         return false;
816 }
817
818 int sof_pcm_stream_free(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream,
819                         struct snd_sof_pcm *spcm, int dir, bool free_widget_list)
820 {
821         const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm);
822         int ret;
823
824         if (spcm->prepared[substream->stream]) {
825                 /* stop DMA first if needed */
826                 if (pcm_ops && pcm_ops->platform_stop_during_hw_free)
827                         snd_sof_pcm_platform_trigger(sdev, substream, SNDRV_PCM_TRIGGER_STOP);
828
829                 /* Send PCM_FREE IPC to reset pipeline */
830                 if (pcm_ops && pcm_ops->hw_free) {
831                         ret = pcm_ops->hw_free(sdev->component, substream);
832                         if (ret < 0)
833                                 return ret;
834                 }
835
836                 spcm->prepared[substream->stream] = false;
837         }
838
839         /* reset the DMA */
840         ret = snd_sof_pcm_platform_hw_free(sdev, substream);
841         if (ret < 0)
842                 return ret;
843
844         /* free widget list */
845         if (free_widget_list) {
846                 ret = sof_widget_list_free(sdev, spcm, dir);
847                 if (ret < 0)
848                         dev_err(sdev->dev, "failed to free widgets during suspend\n");
849         }
850
851         return ret;
852 }
853
854 /*
855  * Generic object lookup APIs.
856  */
857
858 struct snd_sof_pcm *snd_sof_find_spcm_name(struct snd_soc_component *scomp,
859                                            const char *name)
860 {
861         struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
862         struct snd_sof_pcm *spcm;
863
864         list_for_each_entry(spcm, &sdev->pcm_list, list) {
865                 /* match with PCM dai name */
866                 if (strcmp(spcm->pcm.dai_name, name) == 0)
867                         return spcm;
868
869                 /* match with playback caps name if set */
870                 if (*spcm->pcm.caps[0].name &&
871                     !strcmp(spcm->pcm.caps[0].name, name))
872                         return spcm;
873
874                 /* match with capture caps name if set */
875                 if (*spcm->pcm.caps[1].name &&
876                     !strcmp(spcm->pcm.caps[1].name, name))
877                         return spcm;
878         }
879
880         return NULL;
881 }
882
883 struct snd_sof_pcm *snd_sof_find_spcm_comp(struct snd_soc_component *scomp,
884                                            unsigned int comp_id,
885                                            int *direction)
886 {
887         struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
888         struct snd_sof_pcm *spcm;
889         int dir;
890
891         list_for_each_entry(spcm, &sdev->pcm_list, list) {
892                 for_each_pcm_streams(dir) {
893                         if (spcm->stream[dir].comp_id == comp_id) {
894                                 *direction = dir;
895                                 return spcm;
896                         }
897                 }
898         }
899
900         return NULL;
901 }
902
903 struct snd_sof_widget *snd_sof_find_swidget(struct snd_soc_component *scomp,
904                                             const char *name)
905 {
906         struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
907         struct snd_sof_widget *swidget;
908
909         list_for_each_entry(swidget, &sdev->widget_list, list) {
910                 if (strcmp(name, swidget->widget->name) == 0)
911                         return swidget;
912         }
913
914         return NULL;
915 }
916
917 /* find widget by stream name and direction */
918 struct snd_sof_widget *
919 snd_sof_find_swidget_sname(struct snd_soc_component *scomp,
920                            const char *pcm_name, int dir)
921 {
922         struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
923         struct snd_sof_widget *swidget;
924         enum snd_soc_dapm_type type;
925
926         if (dir == SNDRV_PCM_STREAM_PLAYBACK)
927                 type = snd_soc_dapm_aif_in;
928         else
929                 type = snd_soc_dapm_aif_out;
930
931         list_for_each_entry(swidget, &sdev->widget_list, list) {
932                 if (!strcmp(pcm_name, swidget->widget->sname) &&
933                     swidget->id == type)
934                         return swidget;
935         }
936
937         return NULL;
938 }
939
940 struct snd_sof_dai *snd_sof_find_dai(struct snd_soc_component *scomp,
941                                      const char *name)
942 {
943         struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
944         struct snd_sof_dai *dai;
945
946         list_for_each_entry(dai, &sdev->dai_list, list) {
947                 if (dai->name && (strcmp(name, dai->name) == 0))
948                         return dai;
949         }
950
951         return NULL;
952 }
953
954 static int sof_dai_get_clk(struct snd_soc_pcm_runtime *rtd, int clk_type)
955 {
956         struct snd_soc_component *component =
957                 snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME);
958         struct snd_sof_dai *dai =
959                 snd_sof_find_dai(component, (char *)rtd->dai_link->name);
960         struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
961         const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
962
963         /* use the tplg configured mclk if existed */
964         if (!dai)
965                 return 0;
966
967         if (tplg_ops && tplg_ops->dai_get_clk)
968                 return tplg_ops->dai_get_clk(sdev, dai, clk_type);
969
970         return 0;
971 }
972
973 /*
974  * Helper to get SSP MCLK from a pcm_runtime.
975  * Return 0 if not exist.
976  */
977 int sof_dai_get_mclk(struct snd_soc_pcm_runtime *rtd)
978 {
979         return sof_dai_get_clk(rtd, SOF_DAI_CLK_INTEL_SSP_MCLK);
980 }
981 EXPORT_SYMBOL(sof_dai_get_mclk);
982
983 /*
984  * Helper to get SSP BCLK from a pcm_runtime.
985  * Return 0 if not exist.
986  */
987 int sof_dai_get_bclk(struct snd_soc_pcm_runtime *rtd)
988 {
989         return sof_dai_get_clk(rtd, SOF_DAI_CLK_INTEL_SSP_BCLK);
990 }
991 EXPORT_SYMBOL(sof_dai_get_bclk);
992
993 static struct snd_sof_of_mach *sof_of_machine_select(struct snd_sof_dev *sdev)
994 {
995         struct snd_sof_pdata *sof_pdata = sdev->pdata;
996         const struct sof_dev_desc *desc = sof_pdata->desc;
997         struct snd_sof_of_mach *mach = desc->of_machines;
998
999         if (!mach)
1000                 return NULL;
1001
1002         for (; mach->compatible; mach++) {
1003                 if (of_machine_is_compatible(mach->compatible)) {
1004                         sof_pdata->tplg_filename = mach->sof_tplg_filename;
1005                         if (mach->fw_filename)
1006                                 sof_pdata->fw_filename = mach->fw_filename;
1007
1008                         return mach;
1009                 }
1010         }
1011
1012         return NULL;
1013 }
1014
1015 /*
1016  * SOF Driver enumeration.
1017  */
1018 int sof_machine_check(struct snd_sof_dev *sdev)
1019 {
1020         struct snd_sof_pdata *sof_pdata = sdev->pdata;
1021         const struct sof_dev_desc *desc = sof_pdata->desc;
1022         struct snd_soc_acpi_mach *mach;
1023
1024         if (!IS_ENABLED(CONFIG_SND_SOC_SOF_FORCE_NOCODEC_MODE)) {
1025                 const struct snd_sof_of_mach *of_mach;
1026
1027                 if (IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC_DEBUG_SUPPORT) &&
1028                     sof_debug_check_flag(SOF_DBG_FORCE_NOCODEC))
1029                         goto nocodec;
1030
1031                 /* find machine */
1032                 mach = snd_sof_machine_select(sdev);
1033                 if (mach) {
1034                         sof_pdata->machine = mach;
1035                         snd_sof_set_mach_params(mach, sdev);
1036                         return 0;
1037                 }
1038
1039                 of_mach = sof_of_machine_select(sdev);
1040                 if (of_mach) {
1041                         sof_pdata->of_machine = of_mach;
1042                         return 0;
1043                 }
1044
1045                 if (!IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC)) {
1046                         dev_err(sdev->dev, "error: no matching ASoC machine driver found - aborting probe\n");
1047                         return -ENODEV;
1048                 }
1049         } else {
1050                 dev_warn(sdev->dev, "Force to use nocodec mode\n");
1051         }
1052
1053 nocodec:
1054         /* select nocodec mode */
1055         dev_warn(sdev->dev, "Using nocodec machine driver\n");
1056         mach = devm_kzalloc(sdev->dev, sizeof(*mach), GFP_KERNEL);
1057         if (!mach)
1058                 return -ENOMEM;
1059
1060         mach->drv_name = "sof-nocodec";
1061         if (!sof_pdata->tplg_filename)
1062                 sof_pdata->tplg_filename = desc->nocodec_tplg_filename;
1063
1064         sof_pdata->machine = mach;
1065         snd_sof_set_mach_params(mach, sdev);
1066
1067         return 0;
1068 }
1069 EXPORT_SYMBOL(sof_machine_check);
1070
1071 int sof_machine_register(struct snd_sof_dev *sdev, void *pdata)
1072 {
1073         struct snd_sof_pdata *plat_data = pdata;
1074         const char *drv_name;
1075         const void *mach;
1076         int size;
1077
1078         drv_name = plat_data->machine->drv_name;
1079         mach = plat_data->machine;
1080         size = sizeof(*plat_data->machine);
1081
1082         /* register machine driver, pass machine info as pdata */
1083         plat_data->pdev_mach =
1084                 platform_device_register_data(sdev->dev, drv_name,
1085                                               PLATFORM_DEVID_NONE, mach, size);
1086         if (IS_ERR(plat_data->pdev_mach))
1087                 return PTR_ERR(plat_data->pdev_mach);
1088
1089         dev_dbg(sdev->dev, "created machine %s\n",
1090                 dev_name(&plat_data->pdev_mach->dev));
1091
1092         return 0;
1093 }
1094 EXPORT_SYMBOL(sof_machine_register);
1095
1096 void sof_machine_unregister(struct snd_sof_dev *sdev, void *pdata)
1097 {
1098         struct snd_sof_pdata *plat_data = pdata;
1099
1100         if (!IS_ERR_OR_NULL(plat_data->pdev_mach))
1101                 platform_device_unregister(plat_data->pdev_mach);
1102 }
1103 EXPORT_SYMBOL(sof_machine_unregister);