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