xref: /openbmc/linux/sound/soc/sof/intel/hda-dai.c (revision 2bebc3b622c3c300eb3a3f603473429d8264c3b6)
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) 2018 Intel Corporation. All rights reserved.
7 //
8 // Authors: Keyon Jie <yang.jie@linux.intel.com>
9 //
10 
11 #include <sound/pcm_params.h>
12 #include <sound/hdaudio_ext.h>
13 #include <sound/intel-nhlt.h>
14 #include <sound/sof/ipc4/header.h>
15 #include <uapi/sound/sof/header.h>
16 #include "../ipc4-priv.h"
17 #include "../ipc4-topology.h"
18 #include "../sof-priv.h"
19 #include "../sof-audio.h"
20 #include "hda.h"
21 
22 /*
23  * The default method is to fetch NHLT from BIOS. With this parameter set
24  * it is possible to override that with NHLT in the SOF topology manifest.
25  */
26 static bool hda_use_tplg_nhlt;
27 module_param_named(sof_use_tplg_nhlt, hda_use_tplg_nhlt, bool, 0444);
28 MODULE_PARM_DESC(sof_use_tplg_nhlt, "SOF topology nhlt override");
29 
30 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
31 
32 struct hda_pipe_params {
33 	u32 ch;
34 	u32 s_freq;
35 	u32 s_fmt;
36 	u8 linktype;
37 	snd_pcm_format_t format;
38 	int link_index;
39 	int stream;
40 	unsigned int link_bps;
41 };
42 
43 /*
44  * This function checks if the host dma channel corresponding
45  * to the link DMA stream_tag argument is assigned to one
46  * of the FEs connected to the BE DAI.
47  */
48 static bool hda_check_fes(struct snd_soc_pcm_runtime *rtd,
49 			  int dir, int stream_tag)
50 {
51 	struct snd_pcm_substream *fe_substream;
52 	struct hdac_stream *fe_hstream;
53 	struct snd_soc_dpcm *dpcm;
54 
55 	for_each_dpcm_fe(rtd, dir, dpcm) {
56 		fe_substream = snd_soc_dpcm_get_substream(dpcm->fe, dir);
57 		fe_hstream = fe_substream->runtime->private_data;
58 		if (fe_hstream->stream_tag == stream_tag)
59 			return true;
60 	}
61 
62 	return false;
63 }
64 
65 static struct hdac_ext_stream *
66 hda_link_stream_assign(struct hdac_bus *bus,
67 		       struct snd_pcm_substream *substream)
68 {
69 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
70 	struct sof_intel_hda_stream *hda_stream;
71 	const struct sof_intel_dsp_desc *chip;
72 	struct snd_sof_dev *sdev;
73 	struct hdac_ext_stream *res = NULL;
74 	struct hdac_stream *hstream = NULL;
75 
76 	int stream_dir = substream->stream;
77 
78 	if (!bus->ppcap) {
79 		dev_err(bus->dev, "stream type not supported\n");
80 		return NULL;
81 	}
82 
83 	spin_lock_irq(&bus->reg_lock);
84 	list_for_each_entry(hstream, &bus->stream_list, list) {
85 		struct hdac_ext_stream *hext_stream =
86 			stream_to_hdac_ext_stream(hstream);
87 		if (hstream->direction != substream->stream)
88 			continue;
89 
90 		hda_stream = hstream_to_sof_hda_stream(hext_stream);
91 		sdev = hda_stream->sdev;
92 		chip = get_chip_info(sdev->pdata);
93 
94 		/* check if link is available */
95 		if (!hext_stream->link_locked) {
96 			/*
97 			 * choose the first available link for platforms that do not have the
98 			 * PROCEN_FMT_QUIRK set.
99 			 */
100 			if (!(chip->quirks & SOF_INTEL_PROCEN_FMT_QUIRK)) {
101 				res = hext_stream;
102 				break;
103 			}
104 
105 			if (hstream->opened) {
106 				/*
107 				 * check if the stream tag matches the stream
108 				 * tag of one of the connected FEs
109 				 */
110 				if (hda_check_fes(rtd, stream_dir,
111 						  hstream->stream_tag)) {
112 					res = hext_stream;
113 					break;
114 				}
115 			} else {
116 				res = hext_stream;
117 
118 				/*
119 				 * This must be a hostless stream.
120 				 * So reserve the host DMA channel.
121 				 */
122 				hda_stream->host_reserved = 1;
123 				break;
124 			}
125 		}
126 	}
127 
128 	if (res) {
129 		/*
130 		 * Decouple host and link DMA. The decoupled flag
131 		 * is updated in snd_hdac_ext_stream_decouple().
132 		 */
133 		if (!res->decoupled)
134 			snd_hdac_ext_stream_decouple_locked(bus, res, true);
135 
136 		res->link_locked = 1;
137 		res->link_substream = substream;
138 	}
139 	spin_unlock_irq(&bus->reg_lock);
140 
141 	return res;
142 }
143 
144 static int hda_link_dma_cleanup(struct snd_pcm_substream *substream,
145 				struct hdac_stream *hstream,
146 				struct snd_soc_dai *cpu_dai,
147 				struct snd_soc_dai *codec_dai,
148 				bool trigger_suspend_stop)
149 {
150 	struct hdac_ext_stream *hext_stream = snd_soc_dai_get_dma_data(cpu_dai, substream);
151 	struct hdac_bus *bus = hstream->bus;
152 	struct sof_intel_hda_stream *hda_stream;
153 	struct hdac_ext_link *link;
154 	int stream_tag;
155 
156 	link = snd_hdac_ext_bus_get_link(bus, codec_dai->component->name);
157 	if (!link)
158 		return -EINVAL;
159 
160 	if (trigger_suspend_stop)
161 		snd_hdac_ext_link_stream_clear(hext_stream);
162 
163 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
164 		stream_tag = hdac_stream(hext_stream)->stream_tag;
165 		snd_hdac_ext_link_clear_stream_id(link, stream_tag);
166 	}
167 	snd_soc_dai_set_dma_data(cpu_dai, substream, NULL);
168 	snd_hdac_ext_stream_release(hext_stream, HDAC_EXT_STREAM_TYPE_LINK);
169 	hext_stream->link_prepared = 0;
170 
171 	/* free the host DMA channel reserved by hostless streams */
172 	hda_stream = hstream_to_sof_hda_stream(hext_stream);
173 	hda_stream->host_reserved = 0;
174 
175 	return 0;
176 }
177 
178 static int hda_link_dma_params(struct hdac_ext_stream *hext_stream,
179 			       struct hda_pipe_params *params)
180 {
181 	struct hdac_stream *hstream = &hext_stream->hstream;
182 	unsigned char stream_tag = hstream->stream_tag;
183 	struct hdac_bus *bus = hstream->bus;
184 	struct hdac_ext_link *link;
185 	unsigned int format_val;
186 
187 	snd_hdac_ext_stream_decouple(bus, hext_stream, true);
188 	snd_hdac_ext_link_stream_reset(hext_stream);
189 
190 	format_val = snd_hdac_calc_stream_format(params->s_freq, params->ch,
191 						 params->format,
192 						 params->link_bps, 0);
193 
194 	dev_dbg(bus->dev, "format_val=%d, rate=%d, ch=%d, format=%d\n",
195 		format_val, params->s_freq, params->ch, params->format);
196 
197 	snd_hdac_ext_link_stream_setup(hext_stream, format_val);
198 
199 	if (hext_stream->hstream.direction == SNDRV_PCM_STREAM_PLAYBACK) {
200 		list_for_each_entry(link, &bus->hlink_list, list) {
201 			if (link->index == params->link_index)
202 				snd_hdac_ext_link_set_stream_id(link,
203 								stream_tag);
204 		}
205 	}
206 
207 	hext_stream->link_prepared = 1;
208 
209 	return 0;
210 }
211 
212 static int hda_link_dma_hw_params(struct snd_pcm_substream *substream,
213 				  struct snd_pcm_hw_params *params)
214 {
215 	struct hdac_stream *hstream = substream->runtime->private_data;
216 	struct hdac_ext_stream *hext_stream;
217 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
218 	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
219 	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
220 	struct hda_pipe_params p_params = {0};
221 	struct hdac_bus *bus = hstream->bus;
222 	struct hdac_ext_link *link;
223 
224 	/* get stored dma data if resuming from system suspend */
225 	hext_stream = snd_soc_dai_get_dma_data(cpu_dai, substream);
226 	if (!hext_stream) {
227 		hext_stream = hda_link_stream_assign(bus, substream);
228 		if (!hext_stream)
229 			return -EBUSY;
230 
231 		snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)hext_stream);
232 	}
233 
234 	link = snd_hdac_ext_bus_get_link(bus, codec_dai->component->name);
235 	if (!link)
236 		return -EINVAL;
237 
238 	/* set the hdac_stream in the codec dai */
239 	snd_soc_dai_set_stream(codec_dai, hdac_stream(hext_stream), substream->stream);
240 
241 	p_params.s_fmt = snd_pcm_format_width(params_format(params));
242 	p_params.ch = params_channels(params);
243 	p_params.s_freq = params_rate(params);
244 	p_params.stream = substream->stream;
245 	p_params.link_index = link->index;
246 	p_params.format = params_format(params);
247 
248 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
249 		p_params.link_bps = codec_dai->driver->playback.sig_bits;
250 	else
251 		p_params.link_bps = codec_dai->driver->capture.sig_bits;
252 
253 	return hda_link_dma_params(hext_stream, &p_params);
254 }
255 
256 static int hda_link_dma_prepare(struct snd_pcm_substream *substream)
257 {
258 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
259 	int stream = substream->stream;
260 
261 	return hda_link_dma_hw_params(substream, &rtd->dpcm[stream].hw_params);
262 }
263 
264 static int hda_link_dma_trigger(struct snd_pcm_substream *substream, int cmd)
265 {
266 	struct hdac_stream *hstream = substream->runtime->private_data;
267 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
268 	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
269 	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
270 	struct hdac_ext_stream *hext_stream = snd_soc_dai_get_dma_data(cpu_dai, substream);
271 	int ret;
272 
273 	if (!hext_stream)
274 		return 0;
275 
276 	switch (cmd) {
277 	case SNDRV_PCM_TRIGGER_START:
278 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
279 		snd_hdac_ext_link_stream_start(hext_stream);
280 		break;
281 	case SNDRV_PCM_TRIGGER_SUSPEND:
282 	case SNDRV_PCM_TRIGGER_STOP:
283 		ret = hda_link_dma_cleanup(substream, hstream, cpu_dai, codec_dai, true);
284 		if (ret < 0)
285 			return ret;
286 
287 		break;
288 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
289 		snd_hdac_ext_link_stream_clear(hext_stream);
290 
291 		break;
292 	default:
293 		return -EINVAL;
294 	}
295 	return 0;
296 }
297 
298 static int hda_link_dma_hw_free(struct snd_pcm_substream *substream)
299 {
300 	struct hdac_stream *hstream = substream->runtime->private_data;
301 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
302 	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
303 	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
304 	struct hdac_ext_stream *hext_stream;
305 
306 	hext_stream = snd_soc_dai_get_dma_data(cpu_dai, substream);
307 	if (!hext_stream)
308 		return 0;
309 
310 	return hda_link_dma_cleanup(substream, hstream, cpu_dai, codec_dai, false);
311 }
312 
313 static int hda_dai_widget_update(struct snd_soc_dapm_widget *w,
314 				 int channel, bool widget_setup)
315 {
316 	struct snd_sof_dai_config_data data;
317 
318 	data.dai_data = channel;
319 
320 	/* set up/free DAI widget and send DAI_CONFIG IPC */
321 	if (widget_setup)
322 		return hda_ctrl_dai_widget_setup(w, SOF_DAI_CONFIG_FLAGS_2_STEP_STOP, &data);
323 
324 	return hda_ctrl_dai_widget_free(w, SOF_DAI_CONFIG_FLAGS_NONE, &data);
325 }
326 
327 static int hda_dai_hw_params_update(struct snd_pcm_substream *substream,
328 				    struct snd_pcm_hw_params *params,
329 				    struct snd_soc_dai *dai)
330 {
331 	struct hdac_ext_stream *hext_stream;
332 	struct snd_soc_dapm_widget *w;
333 	int stream_tag;
334 
335 	hext_stream = snd_soc_dai_get_dma_data(dai, substream);
336 	if (!hext_stream)
337 		return -EINVAL;
338 
339 	stream_tag = hdac_stream(hext_stream)->stream_tag;
340 
341 	w = snd_soc_dai_get_widget(dai, substream->stream);
342 
343 	/* set up the DAI widget and send the DAI_CONFIG with the new tag */
344 	return hda_dai_widget_update(w, stream_tag - 1, true);
345 }
346 
347 static int hda_dai_hw_params(struct snd_pcm_substream *substream,
348 			     struct snd_pcm_hw_params *params,
349 			     struct snd_soc_dai *dai)
350 {
351 	struct hdac_ext_stream *hext_stream =
352 				snd_soc_dai_get_dma_data(dai, substream);
353 	int ret;
354 
355 	if (hext_stream && hext_stream->link_prepared)
356 		return 0;
357 
358 	ret = hda_link_dma_hw_params(substream, params);
359 	if (ret < 0)
360 		return ret;
361 
362 	return hda_dai_hw_params_update(substream, params, dai);
363 }
364 
365 
366 static int hda_dai_config_pause_push_ipc(struct snd_soc_dapm_widget *w)
367 {
368 	struct snd_sof_widget *swidget = w->dobj.private;
369 	struct snd_soc_component *component = swidget->scomp;
370 	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
371 	const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg;
372 	int ret = 0;
373 
374 	if (tplg_ops->dai_config) {
375 		ret = tplg_ops->dai_config(sdev, swidget, SOF_DAI_CONFIG_FLAGS_PAUSE, NULL);
376 		if (ret < 0)
377 			dev_err(sdev->dev, "%s: DAI config failed for widget %s\n", __func__,
378 				w->name);
379 	}
380 
381 	return ret;
382 }
383 
384 static int hda_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
385 {
386 	struct hdac_ext_stream *hext_stream =
387 				snd_soc_dai_get_dma_data(dai, substream);
388 	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(dai->component);
389 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
390 	int stream = substream->stream;
391 	int ret;
392 
393 	if (hext_stream && hext_stream->link_prepared)
394 		return 0;
395 
396 	dev_dbg(sdev->dev, "prepare stream dir %d\n", substream->stream);
397 
398 	ret = hda_link_dma_prepare(substream);
399 	if (ret < 0)
400 		return ret;
401 
402 	return hda_dai_hw_params_update(substream, &rtd->dpcm[stream].hw_params, dai);
403 }
404 
405 static int hda_dai_hw_free_ipc(int stream, /* direction */
406 			       struct snd_soc_dai *dai)
407 {
408 	struct snd_soc_dapm_widget *w;
409 
410 	w = snd_soc_dai_get_widget(dai, stream);
411 
412 	/* free the link DMA channel in the FW and the DAI widget */
413 	return hda_dai_widget_update(w, DMA_CHAN_INVALID, false);
414 }
415 
416 static int ipc3_hda_dai_trigger(struct snd_pcm_substream *substream,
417 				int cmd, struct snd_soc_dai *dai)
418 {
419 	struct snd_soc_dapm_widget *w;
420 	int ret;
421 
422 	dev_dbg(dai->dev, "cmd=%d dai %s direction %d\n", cmd,
423 		dai->name, substream->stream);
424 
425 	ret = hda_link_dma_trigger(substream, cmd);
426 	if (ret < 0)
427 		return ret;
428 
429 	w = snd_soc_dai_get_widget(dai, substream->stream);
430 
431 	switch (cmd) {
432 	case SNDRV_PCM_TRIGGER_SUSPEND:
433 	case SNDRV_PCM_TRIGGER_STOP:
434 		/*
435 		 * free DAI widget during stop/suspend to keep widget use_count's balanced.
436 		 */
437 		ret = hda_dai_hw_free_ipc(substream->stream, dai);
438 		if (ret < 0)
439 			return ret;
440 
441 		break;
442 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
443 		ret = hda_dai_config_pause_push_ipc(w);
444 		if (ret < 0)
445 			return ret;
446 		break;
447 
448 	default:
449 		break;
450 	}
451 	return 0;
452 }
453 
454 /*
455  * In contrast to IPC3, the dai trigger in IPC4 mixes pipeline state changes
456  * (over IPC channel) and DMA state change (direct host register changes).
457  */
458 static int ipc4_hda_dai_trigger(struct snd_pcm_substream *substream,
459 				int cmd, struct snd_soc_dai *dai)
460 {
461 	struct hdac_ext_stream *hext_stream = snd_soc_dai_get_dma_data(dai, substream);
462 	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(dai->component);
463 	struct snd_soc_pcm_runtime *rtd;
464 	struct snd_sof_widget *swidget;
465 	struct snd_soc_dapm_widget *w;
466 	struct snd_soc_dai *codec_dai;
467 	struct hdac_stream *hstream;
468 	struct snd_soc_dai *cpu_dai;
469 	int ret;
470 
471 	dev_dbg(dai->dev, "cmd=%d dai %s direction %d\n", cmd,
472 		dai->name, substream->stream);
473 
474 	hstream = substream->runtime->private_data;
475 	rtd = asoc_substream_to_rtd(substream);
476 	cpu_dai = asoc_rtd_to_cpu(rtd, 0);
477 	codec_dai = asoc_rtd_to_codec(rtd, 0);
478 
479 	w = snd_soc_dai_get_widget(dai, substream->stream);
480 	swidget = w->dobj.private;
481 
482 	switch (cmd) {
483 	case SNDRV_PCM_TRIGGER_START:
484 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
485 		snd_hdac_ext_link_stream_start(hext_stream);
486 		break;
487 	case SNDRV_PCM_TRIGGER_SUSPEND:
488 	case SNDRV_PCM_TRIGGER_STOP:
489 	{
490 		struct snd_sof_widget *pipe_widget = swidget->pipe_widget;
491 		struct sof_ipc4_pipeline *pipeline = pipe_widget->private;
492 
493 		ret = sof_ipc4_set_pipeline_state(sdev, swidget->pipeline_id,
494 						  SOF_IPC4_PIPE_PAUSED);
495 		if (ret < 0)
496 			return ret;
497 
498 		pipeline->state = SOF_IPC4_PIPE_PAUSED;
499 
500 		snd_hdac_ext_link_stream_clear(hext_stream);
501 
502 		ret = sof_ipc4_set_pipeline_state(sdev, swidget->pipeline_id,
503 						  SOF_IPC4_PIPE_RESET);
504 		if (ret < 0)
505 			return ret;
506 
507 		pipeline->state = SOF_IPC4_PIPE_RESET;
508 
509 		ret = hda_link_dma_cleanup(substream, hstream, cpu_dai, codec_dai, false);
510 		if (ret < 0) {
511 			dev_err(sdev->dev, "%s: failed to clean up link DMA\n", __func__);
512 			return ret;
513 		}
514 		break;
515 	}
516 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
517 	{
518 		struct snd_sof_widget *pipe_widget = swidget->pipe_widget;
519 		struct sof_ipc4_pipeline *pipeline = pipe_widget->private;
520 
521 		ret = sof_ipc4_set_pipeline_state(sdev, swidget->pipeline_id,
522 						  SOF_IPC4_PIPE_PAUSED);
523 		if (ret < 0)
524 			return ret;
525 
526 		pipeline->state = SOF_IPC4_PIPE_PAUSED;
527 
528 		snd_hdac_ext_link_stream_clear(hext_stream);
529 		break;
530 	}
531 	default:
532 		dev_err(sdev->dev, "%s: unknown trigger command %d\n", __func__, cmd);
533 		return -EINVAL;
534 	}
535 
536 	return 0;
537 }
538 
539 static int hda_dai_hw_free(struct snd_pcm_substream *substream,
540 			   struct snd_soc_dai *dai)
541 {
542 	int ret;
543 
544 	ret = hda_link_dma_hw_free(substream);
545 	if (ret < 0)
546 		return ret;
547 
548 	return hda_dai_hw_free_ipc(substream->stream, dai);
549 }
550 
551 static const struct snd_soc_dai_ops ipc3_hda_dai_ops = {
552 	.hw_params = hda_dai_hw_params,
553 	.hw_free = hda_dai_hw_free,
554 	.trigger = ipc3_hda_dai_trigger,
555 	.prepare = hda_dai_prepare,
556 };
557 
558 static int hda_dai_suspend(struct hdac_bus *bus)
559 {
560 	struct snd_soc_pcm_runtime *rtd;
561 	struct hdac_ext_stream *hext_stream;
562 	struct hdac_stream *s;
563 	int ret;
564 
565 	/* set internal flag for BE */
566 	list_for_each_entry(s, &bus->stream_list, list) {
567 
568 		hext_stream = stream_to_hdac_ext_stream(s);
569 
570 		/*
571 		 * clear stream. This should already be taken care for running
572 		 * streams when the SUSPEND trigger is called. But paused
573 		 * streams do not get suspended, so this needs to be done
574 		 * explicitly during suspend.
575 		 */
576 		if (hext_stream->link_substream) {
577 			struct snd_soc_dai *cpu_dai;
578 			struct snd_soc_dai *codec_dai;
579 
580 			rtd = asoc_substream_to_rtd(hext_stream->link_substream);
581 			cpu_dai = asoc_rtd_to_cpu(rtd, 0);
582 			codec_dai = asoc_rtd_to_codec(rtd, 0);
583 
584 			ret = hda_link_dma_cleanup(hext_stream->link_substream, s,
585 						   cpu_dai, codec_dai, false);
586 			if (ret < 0)
587 				return ret;
588 
589 			/* for consistency with TRIGGER_SUSPEND we free DAI resources */
590 			ret = hda_dai_hw_free_ipc(hdac_stream(hext_stream)->direction, cpu_dai);
591 			if (ret < 0)
592 				return ret;
593 		}
594 	}
595 
596 	return 0;
597 }
598 
599 static const struct snd_soc_dai_ops ipc4_hda_dai_ops = {
600 	.hw_params = hda_dai_hw_params,
601 	.hw_free = hda_dai_hw_free,
602 	.trigger = ipc4_hda_dai_trigger,
603 	.prepare = hda_dai_prepare,
604 };
605 
606 #endif
607 
608 /* only one flag used so far to harden hw_params/hw_free/trigger/prepare */
609 struct ssp_dai_dma_data {
610 	bool setup;
611 };
612 
613 static int ssp_dai_setup_or_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai,
614 				 bool setup)
615 {
616 	struct snd_soc_dapm_widget *w;
617 
618 	w = snd_soc_dai_get_widget(dai, substream->stream);
619 
620 	if (setup)
621 		return hda_ctrl_dai_widget_setup(w, SOF_DAI_CONFIG_FLAGS_NONE, NULL);
622 
623 	return hda_ctrl_dai_widget_free(w, SOF_DAI_CONFIG_FLAGS_NONE, NULL);
624 }
625 
626 static int ssp_dai_startup(struct snd_pcm_substream *substream,
627 			   struct snd_soc_dai *dai)
628 {
629 	struct ssp_dai_dma_data *dma_data;
630 
631 	dma_data = kzalloc(sizeof(*dma_data), GFP_KERNEL);
632 	if (!dma_data)
633 		return -ENOMEM;
634 
635 	snd_soc_dai_set_dma_data(dai, substream, dma_data);
636 
637 	return 0;
638 }
639 
640 static int ssp_dai_setup(struct snd_pcm_substream *substream,
641 			 struct snd_soc_dai *dai,
642 			 bool setup)
643 {
644 	struct ssp_dai_dma_data *dma_data;
645 	int ret = 0;
646 
647 	dma_data = snd_soc_dai_get_dma_data(dai, substream);
648 	if (!dma_data) {
649 		dev_err(dai->dev, "%s: failed to get dma_data\n", __func__);
650 		return -EIO;
651 	}
652 
653 	if (dma_data->setup != setup) {
654 		ret = ssp_dai_setup_or_free(substream, dai, setup);
655 		if (!ret)
656 			dma_data->setup = setup;
657 	}
658 	return ret;
659 }
660 
661 static int ssp_dai_hw_params(struct snd_pcm_substream *substream,
662 			     struct snd_pcm_hw_params *params,
663 			     struct snd_soc_dai *dai)
664 {
665 	/* params are ignored for now */
666 	return ssp_dai_setup(substream, dai, true);
667 }
668 
669 static int ssp_dai_prepare(struct snd_pcm_substream *substream,
670 			   struct snd_soc_dai *dai)
671 {
672 	/*
673 	 * the SSP will only be reconfigured during resume operations and
674 	 * not in case of xruns
675 	 */
676 	return ssp_dai_setup(substream, dai, true);
677 }
678 
679 static int ipc3_ssp_dai_trigger(struct snd_pcm_substream *substream,
680 				int cmd, struct snd_soc_dai *dai)
681 {
682 	if (cmd != SNDRV_PCM_TRIGGER_SUSPEND)
683 		return 0;
684 
685 	return ssp_dai_setup(substream, dai, false);
686 }
687 
688 static int ssp_dai_hw_free(struct snd_pcm_substream *substream,
689 			   struct snd_soc_dai *dai)
690 {
691 	return ssp_dai_setup(substream, dai, false);
692 }
693 
694 static void ssp_dai_shutdown(struct snd_pcm_substream *substream,
695 			     struct snd_soc_dai *dai)
696 {
697 	struct ssp_dai_dma_data *dma_data;
698 
699 	dma_data = snd_soc_dai_get_dma_data(dai, substream);
700 	if (!dma_data) {
701 		dev_err(dai->dev, "%s: failed to get dma_data\n", __func__);
702 		return;
703 	}
704 	snd_soc_dai_set_dma_data(dai, substream, NULL);
705 	kfree(dma_data);
706 }
707 
708 static const struct snd_soc_dai_ops ipc3_ssp_dai_ops = {
709 	.startup = ssp_dai_startup,
710 	.hw_params = ssp_dai_hw_params,
711 	.prepare = ssp_dai_prepare,
712 	.trigger = ipc3_ssp_dai_trigger,
713 	.hw_free = ssp_dai_hw_free,
714 	.shutdown = ssp_dai_shutdown,
715 };
716 
717 static int ipc4_be_dai_trigger(struct snd_pcm_substream *substream,
718 			       int cmd, struct snd_soc_dai *dai)
719 {
720 	struct snd_sof_widget *pipe_widget;
721 	struct sof_ipc4_pipeline *pipeline;
722 	struct snd_sof_widget *swidget;
723 	struct snd_soc_dapm_widget *w;
724 	struct snd_sof_dev *sdev;
725 	int ret;
726 
727 	w = snd_soc_dai_get_widget(dai, substream->stream);
728 	swidget = w->dobj.private;
729 	pipe_widget = swidget->pipe_widget;
730 	pipeline = pipe_widget->private;
731 	sdev = snd_soc_component_get_drvdata(swidget->scomp);
732 
733 	switch (cmd) {
734 	case SNDRV_PCM_TRIGGER_SUSPEND:
735 	case SNDRV_PCM_TRIGGER_STOP:
736 		ret = sof_ipc4_set_pipeline_state(sdev, swidget->pipeline_id,
737 						  SOF_IPC4_PIPE_PAUSED);
738 		if (ret < 0)
739 			return ret;
740 		pipeline->state = SOF_IPC4_PIPE_PAUSED;
741 
742 		ret = sof_ipc4_set_pipeline_state(sdev, swidget->pipeline_id,
743 						  SOF_IPC4_PIPE_RESET);
744 		if (ret < 0)
745 			return ret;
746 		pipeline->state = SOF_IPC4_PIPE_RESET;
747 		break;
748 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
749 		ret = sof_ipc4_set_pipeline_state(sdev, swidget->pipeline_id,
750 						  SOF_IPC4_PIPE_PAUSED);
751 		if (ret < 0)
752 			return ret;
753 		pipeline->state = SOF_IPC4_PIPE_PAUSED;
754 		break;
755 	default:
756 		break;
757 	}
758 
759 	return 0;
760 }
761 
762 static const struct snd_soc_dai_ops ipc4_dmic_dai_ops = {
763 	.trigger = ipc4_be_dai_trigger,
764 };
765 
766 static const struct snd_soc_dai_ops ipc4_ssp_dai_ops = {
767 	.trigger = ipc4_be_dai_trigger,
768 };
769 
770 void hda_set_dai_drv_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *ops)
771 {
772 	int i;
773 
774 	switch (sdev->pdata->ipc_type) {
775 	case SOF_IPC:
776 		for (i = 0; i < ops->num_drv; i++) {
777 			if (strstr(ops->drv[i].name, "SSP")) {
778 				ops->drv[i].ops = &ipc3_ssp_dai_ops;
779 				continue;
780 			}
781 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
782 			if (strstr(ops->drv[i].name, "iDisp") ||
783 			    strstr(ops->drv[i].name, "Analog") ||
784 			    strstr(ops->drv[i].name, "Digital"))
785 				ops->drv[i].ops = &ipc3_hda_dai_ops;
786 #endif
787 		}
788 		break;
789 	case SOF_INTEL_IPC4:
790 	{
791 		struct sof_ipc4_fw_data *ipc4_data = sdev->private;
792 
793 		for (i = 0; i < ops->num_drv; i++) {
794 			if (strstr(ops->drv[i].name, "DMIC")) {
795 				ops->drv[i].ops = &ipc4_dmic_dai_ops;
796 				continue;
797 			}
798 			if (strstr(ops->drv[i].name, "SSP")) {
799 				ops->drv[i].ops = &ipc4_ssp_dai_ops;
800 				continue;
801 			}
802 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
803 			if (strstr(ops->drv[i].name, "iDisp") ||
804 			    strstr(ops->drv[i].name, "Analog") ||
805 			    strstr(ops->drv[i].name, "Digital"))
806 				ops->drv[i].ops = &ipc4_hda_dai_ops;
807 #endif
808 		}
809 
810 		if (!hda_use_tplg_nhlt)
811 			ipc4_data->nhlt = intel_nhlt_init(sdev->dev);
812 
813 		break;
814 	}
815 	default:
816 		break;
817 	}
818 }
819 
820 void hda_ops_free(struct snd_sof_dev *sdev)
821 {
822 	if (sdev->pdata->ipc_type == SOF_INTEL_IPC4) {
823 		struct sof_ipc4_fw_data *ipc4_data = sdev->private;
824 
825 		if (!hda_use_tplg_nhlt)
826 			intel_nhlt_free(ipc4_data->nhlt);
827 	}
828 }
829 EXPORT_SYMBOL_NS(hda_ops_free, SND_SOC_SOF_INTEL_HDA_COMMON);
830 
831 /*
832  * common dai driver for skl+ platforms.
833  * some products who use this DAI array only physically have a subset of
834  * the DAIs, but no harm is done here by adding the whole set.
835  */
836 struct snd_soc_dai_driver skl_dai[] = {
837 {
838 	.name = "SSP0 Pin",
839 	.playback = {
840 		.channels_min = 1,
841 		.channels_max = 8,
842 	},
843 	.capture = {
844 		.channels_min = 1,
845 		.channels_max = 8,
846 	},
847 },
848 {
849 	.name = "SSP1 Pin",
850 	.playback = {
851 		.channels_min = 1,
852 		.channels_max = 8,
853 	},
854 	.capture = {
855 		.channels_min = 1,
856 		.channels_max = 8,
857 	},
858 },
859 {
860 	.name = "SSP2 Pin",
861 	.playback = {
862 		.channels_min = 1,
863 		.channels_max = 8,
864 	},
865 	.capture = {
866 		.channels_min = 1,
867 		.channels_max = 8,
868 	},
869 },
870 {
871 	.name = "SSP3 Pin",
872 	.playback = {
873 		.channels_min = 1,
874 		.channels_max = 8,
875 	},
876 	.capture = {
877 		.channels_min = 1,
878 		.channels_max = 8,
879 	},
880 },
881 {
882 	.name = "SSP4 Pin",
883 	.playback = {
884 		.channels_min = 1,
885 		.channels_max = 8,
886 	},
887 	.capture = {
888 		.channels_min = 1,
889 		.channels_max = 8,
890 	},
891 },
892 {
893 	.name = "SSP5 Pin",
894 	.playback = {
895 		.channels_min = 1,
896 		.channels_max = 8,
897 	},
898 	.capture = {
899 		.channels_min = 1,
900 		.channels_max = 8,
901 	},
902 },
903 {
904 	.name = "DMIC01 Pin",
905 	.capture = {
906 		.channels_min = 1,
907 		.channels_max = 4,
908 	},
909 },
910 {
911 	.name = "DMIC16k Pin",
912 	.capture = {
913 		.channels_min = 1,
914 		.channels_max = 4,
915 	},
916 },
917 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
918 {
919 	.name = "iDisp1 Pin",
920 	.playback = {
921 		.channels_min = 1,
922 		.channels_max = 8,
923 	},
924 },
925 {
926 	.name = "iDisp2 Pin",
927 	.playback = {
928 		.channels_min = 1,
929 		.channels_max = 8,
930 	},
931 },
932 {
933 	.name = "iDisp3 Pin",
934 	.playback = {
935 		.channels_min = 1,
936 		.channels_max = 8,
937 	},
938 },
939 {
940 	.name = "iDisp4 Pin",
941 	.playback = {
942 		.channels_min = 1,
943 		.channels_max = 8,
944 	},
945 },
946 {
947 	.name = "Analog CPU DAI",
948 	.playback = {
949 		.channels_min = 1,
950 		.channels_max = 16,
951 	},
952 	.capture = {
953 		.channels_min = 1,
954 		.channels_max = 16,
955 	},
956 },
957 {
958 	.name = "Digital CPU DAI",
959 	.playback = {
960 		.channels_min = 1,
961 		.channels_max = 16,
962 	},
963 	.capture = {
964 		.channels_min = 1,
965 		.channels_max = 16,
966 	},
967 },
968 {
969 	.name = "Alt Analog CPU DAI",
970 	.playback = {
971 		.channels_min = 1,
972 		.channels_max = 16,
973 	},
974 	.capture = {
975 		.channels_min = 1,
976 		.channels_max = 16,
977 	},
978 },
979 #endif
980 };
981 
982 int hda_dsp_dais_suspend(struct snd_sof_dev *sdev)
983 {
984 	/*
985 	 * In the corner case where a SUSPEND happens during a PAUSE, the ALSA core
986 	 * does not throw the TRIGGER_SUSPEND. This leaves the DAIs in an unbalanced state.
987 	 * Since the component suspend is called last, we can trap this corner case
988 	 * and force the DAIs to release their resources.
989 	 */
990 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
991 	int ret;
992 
993 	ret = hda_dai_suspend(sof_to_bus(sdev));
994 	if (ret < 0)
995 		return ret;
996 #endif
997 
998 	return 0;
999 }
1000