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