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