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