xref: /linux/sound/soc/sof/intel/hda-dai.c (revision ca220141fa8ebae09765a242076b2b77338106b0)
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
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/hda-mlink.h>
14 #include <sound/hda_register.h>
15 #include <sound/intel-nhlt.h>
16 #include <sound/sof/ipc4/header.h>
17 #include <uapi/sound/sof/header.h>
18 #include "../ipc4-priv.h"
19 #include "../ipc4-topology.h"
20 #include "../sof-priv.h"
21 #include "../sof-audio.h"
22 #include "hda.h"
23 
24 /*
25  * The default method is to fetch NHLT from BIOS. With this parameter set
26  * it is possible to override that with NHLT in the SOF topology manifest.
27  */
28 static bool hda_use_tplg_nhlt;
29 module_param_named(sof_use_tplg_nhlt, hda_use_tplg_nhlt, bool, 0444);
30 MODULE_PARM_DESC(sof_use_tplg_nhlt, "SOF topology nhlt override");
31 
32 int hda_dai_config(struct snd_soc_dapm_widget *w, unsigned int flags,
33 		   struct snd_sof_dai_config_data *data)
34 {
35 	struct snd_sof_widget *swidget = w->dobj.private;
36 	const struct sof_ipc_tplg_ops *tplg_ops;
37 	struct snd_sof_dev *sdev;
38 	int ret;
39 
40 	if (!swidget)
41 		return 0;
42 
43 	sdev = widget_to_sdev(w);
44 	tplg_ops = sof_ipc_get_ops(sdev, tplg);
45 
46 	if (tplg_ops && tplg_ops->dai_config) {
47 		ret = tplg_ops->dai_config(sdev, swidget, flags, data);
48 		if (ret < 0) {
49 			dev_err(sdev->dev, "DAI config with flags %x failed for widget %s\n",
50 				flags, w->name);
51 			return ret;
52 		}
53 	}
54 
55 	return 0;
56 }
57 EXPORT_SYMBOL_NS(hda_dai_config, "SND_SOC_SOF_INTEL_HDA_COMMON");
58 
59 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_LINK)
60 
61 static struct snd_sof_dev *dai_to_sdev(struct snd_pcm_substream *substream,
62 				       struct snd_soc_dai *cpu_dai)
63 {
64 	struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream);
65 
66 	return widget_to_sdev(w);
67 }
68 
69 static const struct hda_dai_widget_dma_ops *
70 hda_dai_get_ops(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai)
71 {
72 	struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream);
73 	struct snd_sof_widget *swidget;
74 	struct snd_sof_dev *sdev;
75 	struct snd_sof_dai *sdai;
76 
77 	/*
78 	 * this is unlikely if the topology and the machine driver DAI links match.
79 	 * But if there's a missing DAI link in topology, this will prevent a NULL pointer
80 	 * dereference later on.
81 	 */
82 	if (!w) {
83 		dev_err(cpu_dai->dev, "%s: widget is NULL\n", __func__);
84 		return NULL;
85 	}
86 
87 	sdev = widget_to_sdev(w);
88 	swidget = w->dobj.private;
89 	if (!swidget) {
90 		dev_err(sdev->dev, "%s: swidget is NULL\n", __func__);
91 		return NULL;
92 	}
93 
94 	if (sdev->dspless_mode_selected)
95 		return hda_select_dai_widget_ops(sdev, swidget);
96 
97 	sdai = swidget->private;
98 
99 	/* select and set the DAI widget ops if not set already */
100 	if (!sdai->platform_private) {
101 		const struct hda_dai_widget_dma_ops *ops =
102 			hda_select_dai_widget_ops(sdev, swidget);
103 		if (!ops)
104 			return NULL;
105 
106 		/* check if mandatory ops are set */
107 		if (!ops || !ops->get_hext_stream)
108 			return NULL;
109 
110 		sdai->platform_private = ops;
111 	}
112 
113 	return sdai->platform_private;
114 }
115 
116 static int
117 hda_link_dma_cleanup(struct snd_pcm_substream *substream,
118 		     struct hdac_ext_stream *hext_stream,
119 		     struct snd_soc_dai *cpu_dai, bool release)
120 {
121 	const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai);
122 	struct sof_intel_hda_stream *hda_stream;
123 	struct hdac_ext_link *hlink;
124 	struct snd_sof_dev *sdev;
125 	int stream_tag;
126 
127 	if (!ops) {
128 		dev_err(cpu_dai->dev, "DAI widget ops not set\n");
129 		return -EINVAL;
130 	}
131 
132 	sdev = dai_to_sdev(substream, cpu_dai);
133 
134 	hlink = ops->get_hlink(sdev, substream);
135 	if (!hlink)
136 		return -EINVAL;
137 
138 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
139 		stream_tag = hdac_stream(hext_stream)->stream_tag;
140 		snd_hdac_ext_bus_link_clear_stream_id(hlink, stream_tag);
141 	}
142 
143 	if (!release) {
144 		/*
145 		 * Force stream reconfiguration without releasing the channel on
146 		 * subsequent stream restart (without free), including LinkDMA
147 		 * reset.
148 		 * The stream is released via hda_dai_hw_free()
149 		 */
150 		hext_stream->link_prepared = 0;
151 		return 0;
152 	}
153 
154 	if (ops->release_hext_stream)
155 		ops->release_hext_stream(sdev, cpu_dai, substream);
156 
157 	hext_stream->link_prepared = 0;
158 
159 	/* free the host DMA channel reserved by hostless streams */
160 	hda_stream = hstream_to_sof_hda_stream(hext_stream);
161 	hda_stream->host_reserved = 0;
162 
163 	return 0;
164 }
165 
166 static int hda_link_dma_hw_params(struct snd_pcm_substream *substream,
167 				  struct snd_pcm_hw_params *params, struct snd_soc_dai *cpu_dai)
168 {
169 	const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai);
170 	struct hdac_ext_stream *hext_stream;
171 	struct hdac_stream *hstream;
172 	struct hdac_ext_link *hlink;
173 	struct snd_sof_dev *sdev;
174 	int stream_tag;
175 
176 	if (!ops) {
177 		dev_err(cpu_dai->dev, "DAI widget ops not set\n");
178 		return -EINVAL;
179 	}
180 
181 	sdev = dai_to_sdev(substream, cpu_dai);
182 
183 	hlink = ops->get_hlink(sdev, substream);
184 	if (!hlink)
185 		return -EINVAL;
186 
187 	hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream);
188 
189 	if (!hext_stream) {
190 		if (ops->assign_hext_stream)
191 			hext_stream = ops->assign_hext_stream(sdev, cpu_dai, substream);
192 	}
193 
194 	if (!hext_stream)
195 		return -EBUSY;
196 
197 	hstream = &hext_stream->hstream;
198 	stream_tag = hstream->stream_tag;
199 
200 	if (hext_stream->hstream.direction == SNDRV_PCM_STREAM_PLAYBACK)
201 		snd_hdac_ext_bus_link_set_stream_id(hlink, stream_tag);
202 
203 	/* set the hdac_stream in the codec dai */
204 	if (ops->codec_dai_set_stream)
205 		ops->codec_dai_set_stream(sdev, substream, hstream);
206 
207 	if (ops->reset_hext_stream)
208 		ops->reset_hext_stream(sdev, hext_stream);
209 
210 	if (ops->calc_stream_format && ops->setup_hext_stream) {
211 		unsigned int format_val = ops->calc_stream_format(sdev, substream, params);
212 
213 		ops->setup_hext_stream(sdev, hext_stream, format_val);
214 	}
215 
216 	hext_stream->link_prepared = 1;
217 
218 	return 0;
219 }
220 
221 static int __maybe_unused hda_dai_hw_free(struct snd_pcm_substream *substream,
222 					  struct snd_soc_dai *cpu_dai)
223 {
224 	const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai);
225 	struct hdac_ext_stream *hext_stream;
226 	struct snd_sof_dev *sdev = dai_to_sdev(substream, cpu_dai);
227 
228 	if (!ops) {
229 		dev_err(cpu_dai->dev, "DAI widget ops not set\n");
230 		return -EINVAL;
231 	}
232 
233 	hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream);
234 	if (!hext_stream)
235 		return 0;
236 
237 	return hda_link_dma_cleanup(substream, hext_stream, cpu_dai, true);
238 }
239 
240 static int __maybe_unused hda_dai_hw_params_data(struct snd_pcm_substream *substream,
241 						 struct snd_pcm_hw_params *params,
242 						 struct snd_soc_dai *dai,
243 						 struct snd_sof_dai_config_data *data,
244 						 unsigned int flags)
245 {
246 	struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(dai, substream->stream);
247 	const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, dai);
248 	struct hdac_ext_stream *hext_stream;
249 	struct snd_sof_dev *sdev = widget_to_sdev(w);
250 	int ret;
251 
252 	if (!ops) {
253 		dev_err(sdev->dev, "DAI widget ops not set\n");
254 		return -EINVAL;
255 	}
256 
257 	hext_stream = ops->get_hext_stream(sdev, dai, substream);
258 	if (hext_stream && hext_stream->link_prepared)
259 		return 0;
260 
261 	ret = hda_link_dma_hw_params(substream, params, dai);
262 	if (ret < 0)
263 		return ret;
264 
265 	hext_stream = ops->get_hext_stream(sdev, dai, substream);
266 
267 	flags |= SOF_DAI_CONFIG_FLAGS_2_STEP_STOP << SOF_DAI_CONFIG_FLAGS_QUIRK_SHIFT;
268 	data->dai_data = hdac_stream(hext_stream)->stream_tag - 1;
269 
270 	return hda_dai_config(w, flags, data);
271 }
272 
273 static int __maybe_unused hda_dai_hw_params(struct snd_pcm_substream *substream,
274 					    struct snd_pcm_hw_params *params,
275 					    struct snd_soc_dai *dai)
276 {
277 	struct snd_sof_dai_config_data data = { 0 };
278 	unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS;
279 
280 	return hda_dai_hw_params_data(substream, params, dai, &data, flags);
281 }
282 
283 /*
284  * In contrast to IPC3, the dai trigger in IPC4 mixes pipeline state changes
285  * (over IPC channel) and DMA state change (direct host register changes).
286  */
287 static int __maybe_unused hda_dai_trigger(struct snd_pcm_substream *substream, int cmd,
288 					  struct snd_soc_dai *dai)
289 {
290 	const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, dai);
291 	struct hdac_ext_stream *hext_stream;
292 	struct snd_sof_dev *sdev;
293 	int ret;
294 
295 	if (!ops) {
296 		dev_err(dai->dev, "DAI widget ops not set\n");
297 		return -EINVAL;
298 	}
299 
300 	dev_dbg(dai->dev, "cmd=%d dai %s direction %d\n", cmd,
301 		dai->name, substream->stream);
302 
303 	sdev = dai_to_sdev(substream, dai);
304 
305 	hext_stream = ops->get_hext_stream(sdev, dai, substream);
306 	if (!hext_stream)
307 		return -EINVAL;
308 
309 	if (ops->pre_trigger) {
310 		ret = ops->pre_trigger(sdev, dai, substream, cmd);
311 		if (ret < 0)
312 			return ret;
313 	}
314 
315 	if (ops->trigger) {
316 		ret = ops->trigger(sdev, dai, substream, cmd);
317 		if (ret < 0)
318 			return ret;
319 	}
320 
321 	if (ops->post_trigger) {
322 		ret = ops->post_trigger(sdev, dai, substream, cmd);
323 		if (ret < 0)
324 			return ret;
325 	}
326 
327 	switch (cmd) {
328 	case SNDRV_PCM_TRIGGER_STOP:
329 	case SNDRV_PCM_TRIGGER_SUSPEND:
330 		ret = hda_link_dma_cleanup(substream, hext_stream, dai,
331 					   cmd != SNDRV_PCM_TRIGGER_STOP);
332 		if (ret < 0) {
333 			dev_err(sdev->dev, "%s: failed to clean up link DMA\n", __func__);
334 			return ret;
335 		}
336 		break;
337 	default:
338 		break;
339 	}
340 
341 	return 0;
342 }
343 
344 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC)
345 
346 static int hda_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
347 {
348 	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
349 	int stream = substream->stream;
350 
351 	return hda_dai_hw_params(substream, &rtd->dpcm[stream].hw_params, dai);
352 }
353 
354 static const struct snd_soc_dai_ops hda_dai_ops = {
355 	.hw_params = hda_dai_hw_params,
356 	.hw_free = hda_dai_hw_free,
357 	.trigger = hda_dai_trigger,
358 	.prepare = hda_dai_prepare,
359 };
360 
361 #endif
362 
363 static struct sof_ipc4_copier *widget_to_copier(struct snd_soc_dapm_widget *w)
364 {
365 	struct snd_sof_widget *swidget = w->dobj.private;
366 	struct snd_sof_dai *sdai = swidget->private;
367 	struct sof_ipc4_copier *ipc4_copier = (struct sof_ipc4_copier *)sdai->private;
368 
369 	return ipc4_copier;
370 }
371 
372 static int non_hda_dai_hw_params_data(struct snd_pcm_substream *substream,
373 				      struct snd_pcm_hw_params *params,
374 				      struct snd_soc_dai *cpu_dai,
375 				      struct snd_sof_dai_config_data *data,
376 				      unsigned int flags)
377 {
378 	struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream);
379 	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
380 	struct sof_ipc4_dma_config_tlv *dma_config_tlv;
381 	const struct hda_dai_widget_dma_ops *ops;
382 	struct sof_ipc4_dma_config *dma_config;
383 	struct sof_ipc4_copier *ipc4_copier;
384 	struct hdac_ext_stream *hext_stream;
385 	struct hdac_stream *hstream;
386 	struct snd_sof_dev *sdev;
387 	struct snd_soc_dai *dai;
388 	int cpu_dai_id;
389 	int stream_id;
390 	int ret;
391 
392 	ops = hda_dai_get_ops(substream, cpu_dai);
393 	if (!ops) {
394 		dev_err(cpu_dai->dev, "DAI widget ops not set\n");
395 		return -EINVAL;
396 	}
397 
398 	sdev = widget_to_sdev(w);
399 	hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream);
400 
401 	/* nothing more to do if the link is already prepared */
402 	if (hext_stream && hext_stream->link_prepared)
403 		return 0;
404 
405 	/* use HDaudio stream handling */
406 	ret = hda_dai_hw_params_data(substream, params, cpu_dai, data, flags);
407 	if (ret < 0) {
408 		dev_err(cpu_dai->dev, "%s: hda_dai_hw_params_data failed: %d\n", __func__, ret);
409 		return ret;
410 	}
411 
412 	if (sdev->dspless_mode_selected)
413 		return 0;
414 
415 	/* get stream_id */
416 	hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream);
417 
418 	if (!hext_stream) {
419 		dev_err(cpu_dai->dev, "%s: no hext_stream found\n", __func__);
420 		return -ENODEV;
421 	}
422 
423 	hstream = &hext_stream->hstream;
424 	stream_id = hstream->stream_tag;
425 
426 	if (!stream_id) {
427 		dev_err(cpu_dai->dev, "%s: no stream_id allocated\n", __func__);
428 		return -ENODEV;
429 	}
430 
431 	/* configure TLV */
432 	ipc4_copier = widget_to_copier(w);
433 
434 	for_each_rtd_cpu_dais(rtd, cpu_dai_id, dai) {
435 		if (dai == cpu_dai)
436 			break;
437 	}
438 
439 	dma_config_tlv = &ipc4_copier->dma_config_tlv[cpu_dai_id];
440 	dma_config_tlv->type = SOF_IPC4_GTW_DMA_CONFIG_ID;
441 	/* dma_config_priv_size is zero */
442 	dma_config_tlv->length = sizeof(dma_config_tlv->dma_config);
443 
444 	dma_config = &dma_config_tlv->dma_config;
445 
446 	dma_config->dma_method = SOF_IPC4_DMA_METHOD_HDA;
447 	dma_config->pre_allocated_by_host = 1;
448 	dma_config->dma_channel_id = stream_id - 1;
449 	dma_config->stream_id = stream_id;
450 	/*
451 	 * Currently we use a DMA for each device in ALH blob. The device will
452 	 * be copied in sof_ipc4_prepare_copier_module.
453 	 */
454 	dma_config->dma_stream_channel_map.device_count = 1;
455 	dma_config->dma_priv_config_size = 0;
456 
457 	return 0;
458 }
459 
460 static int non_hda_dai_hw_params(struct snd_pcm_substream *substream,
461 				 struct snd_pcm_hw_params *params,
462 				 struct snd_soc_dai *cpu_dai)
463 {
464 	struct snd_sof_dai_config_data data = { 0 };
465 	unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS;
466 
467 	return non_hda_dai_hw_params_data(substream, params, cpu_dai, &data, flags);
468 }
469 
470 static int non_hda_dai_prepare(struct snd_pcm_substream *substream,
471 			       struct snd_soc_dai *cpu_dai)
472 {
473 	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
474 	int stream = substream->stream;
475 
476 	return non_hda_dai_hw_params(substream, &rtd->dpcm[stream].hw_params, cpu_dai);
477 }
478 
479 static const struct snd_soc_dai_ops ssp_dai_ops = {
480 	.hw_params = non_hda_dai_hw_params,
481 	.hw_free = hda_dai_hw_free,
482 	.trigger = hda_dai_trigger,
483 	.prepare = non_hda_dai_prepare,
484 };
485 
486 static const struct snd_soc_dai_ops dmic_dai_ops = {
487 	.hw_params = non_hda_dai_hw_params,
488 	.hw_free = hda_dai_hw_free,
489 	.trigger = hda_dai_trigger,
490 	.prepare = non_hda_dai_prepare,
491 };
492 
493 int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream,
494 			  struct snd_pcm_hw_params *params,
495 			  struct snd_soc_dai *cpu_dai,
496 			  int link_id,
497 			  int intel_alh_id)
498 {
499 	struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream);
500 	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
501 	struct sof_ipc4_dma_config_tlv *dma_config_tlv;
502 	struct snd_sof_dai_config_data data = { 0 };
503 	unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS;
504 	const struct hda_dai_widget_dma_ops *ops;
505 	struct sof_ipc4_dma_config *dma_config;
506 	struct sof_ipc4_copier *ipc4_copier;
507 	struct hdac_ext_stream *hext_stream;
508 	struct snd_soc_dai *dai;
509 	struct snd_sof_dev *sdev;
510 	bool cpu_dai_found = false;
511 	int cpu_dai_id;
512 	int ch_mask;
513 	int ret;
514 	int i;
515 
516 	if (!w) {
517 		dev_err(cpu_dai->dev, "%s widget not found, check amp link num in the topology\n",
518 			cpu_dai->name);
519 		return -EINVAL;
520 	}
521 
522 	ops = hda_dai_get_ops(substream, cpu_dai);
523 	if (!ops) {
524 		dev_err(cpu_dai->dev, "DAI widget ops not set\n");
525 		return -EINVAL;
526 	}
527 
528 	sdev = widget_to_sdev(w);
529 	hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream);
530 
531 	/* nothing more to do if the link is already prepared */
532 	if (hext_stream && hext_stream->link_prepared)
533 		return 0;
534 
535 	/*
536 	 * reset the PCMSyCM registers to handle a prepare callback when the PCM is restarted
537 	 * due to xruns or after a call to snd_pcm_drain/drop()
538 	 */
539 	ret = hdac_bus_eml_sdw_map_stream_ch(sof_to_bus(sdev), link_id, cpu_dai->id,
540 					     0, 0, substream->stream);
541 	if (ret < 0) {
542 		dev_err(cpu_dai->dev, "%s:  hdac_bus_eml_sdw_map_stream_ch failed %d\n",
543 			__func__, ret);
544 		return ret;
545 	}
546 
547 	data.dai_index = (link_id << 8) | cpu_dai->id;
548 	data.dai_node_id = intel_alh_id;
549 	ret = non_hda_dai_hw_params_data(substream, params, cpu_dai, &data, flags);
550 	if (ret < 0) {
551 		dev_err(cpu_dai->dev, "%s: non_hda_dai_hw_params failed %d\n", __func__, ret);
552 		return ret;
553 	}
554 
555 	hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream);
556 	if (!hext_stream)
557 		return -ENODEV;
558 
559 	/*
560 	 * in the case of SoundWire we need to program the PCMSyCM registers. In case
561 	 * of aggregated devices, we need to define the channel mask for each sublink
562 	 * by reconstructing the split done in soc-pcm.c
563 	 */
564 	for_each_rtd_cpu_dais(rtd, cpu_dai_id, dai) {
565 		if (dai == cpu_dai) {
566 			cpu_dai_found = true;
567 			break;
568 		}
569 	}
570 
571 	if (!cpu_dai_found)
572 		return -ENODEV;
573 
574 	ch_mask = GENMASK(params_channels(params) - 1, 0);
575 
576 	ret = hdac_bus_eml_sdw_map_stream_ch(sof_to_bus(sdev), link_id, cpu_dai->id,
577 					     ch_mask,
578 					     hdac_stream(hext_stream)->stream_tag,
579 					     substream->stream);
580 	if (ret < 0) {
581 		dev_err(cpu_dai->dev, "%s:  hdac_bus_eml_sdw_map_stream_ch failed %d\n",
582 			__func__, ret);
583 		return ret;
584 	}
585 
586 	if (sdev->dspless_mode_selected)
587 		return 0;
588 
589 	ipc4_copier = widget_to_copier(w);
590 	dma_config_tlv = &ipc4_copier->dma_config_tlv[cpu_dai_id];
591 	dma_config = &dma_config_tlv->dma_config;
592 	dma_config->dma_stream_channel_map.mapping[0].device = data.dai_index;
593 	dma_config->dma_stream_channel_map.mapping[0].channel_mask = ch_mask;
594 
595 	/*
596 	 * copy the dma_config_tlv to all ipc4_copier in the same link. Because only one copier
597 	 * will be handled in sof_ipc4_prepare_copier_module.
598 	 */
599 	for_each_rtd_cpu_dais(rtd, i, dai) {
600 		w = snd_soc_dai_get_widget(dai, substream->stream);
601 		if (!w) {
602 			dev_err(cpu_dai->dev,
603 				"%s widget not found, check amp link num in the topology\n",
604 				dai->name);
605 			return -EINVAL;
606 		}
607 		ipc4_copier = widget_to_copier(w);
608 		memcpy(&ipc4_copier->dma_config_tlv[cpu_dai_id], dma_config_tlv,
609 		       sizeof(*dma_config_tlv));
610 	}
611 	return 0;
612 }
613 EXPORT_SYMBOL_NS(sdw_hda_dai_hw_params, "SND_SOC_SOF_INTEL_HDA_COMMON");
614 
615 int sdw_hda_dai_hw_free(struct snd_pcm_substream *substream,
616 			struct snd_soc_dai *cpu_dai,
617 			int link_id)
618 {
619 	struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream);
620 	struct snd_sof_dev *sdev;
621 	int ret;
622 
623 	ret = hda_dai_hw_free(substream, cpu_dai);
624 	if (ret < 0) {
625 		dev_err(cpu_dai->dev, "%s: non_hda_dai_hw_free failed %d\n", __func__, ret);
626 		return ret;
627 	}
628 
629 	sdev = widget_to_sdev(w);
630 
631 	/* in the case of SoundWire we need to reset the PCMSyCM registers */
632 	ret = hdac_bus_eml_sdw_map_stream_ch(sof_to_bus(sdev), link_id, cpu_dai->id,
633 					     0, 0, substream->stream);
634 	if (ret < 0) {
635 		dev_err(cpu_dai->dev, "%s:  hdac_bus_eml_sdw_map_stream_ch failed %d\n",
636 			__func__, ret);
637 		return ret;
638 	}
639 
640 	return 0;
641 }
642 EXPORT_SYMBOL_NS(sdw_hda_dai_hw_free, "SND_SOC_SOF_INTEL_HDA_COMMON");
643 
644 int sdw_hda_dai_trigger(struct snd_pcm_substream *substream, int cmd,
645 			struct snd_soc_dai *cpu_dai)
646 {
647 	return hda_dai_trigger(substream, cmd, cpu_dai);
648 }
649 EXPORT_SYMBOL_NS(sdw_hda_dai_trigger, "SND_SOC_SOF_INTEL_HDA_COMMON");
650 
651 static int hda_dai_suspend(struct hdac_bus *bus)
652 {
653 	struct snd_soc_pcm_runtime *rtd;
654 	struct hdac_ext_stream *hext_stream;
655 	struct hdac_stream *s;
656 	int ret;
657 
658 	/* set internal flag for BE */
659 	list_for_each_entry(s, &bus->stream_list, list) {
660 
661 		hext_stream = stream_to_hdac_ext_stream(s);
662 
663 		/*
664 		 * clear stream. This should already be taken care for running
665 		 * streams when the SUSPEND trigger is called. But paused
666 		 * streams do not get suspended, so this needs to be done
667 		 * explicitly during suspend.
668 		 */
669 		if (hext_stream->link_substream) {
670 			const struct hda_dai_widget_dma_ops *ops;
671 			struct snd_sof_widget *swidget;
672 			struct snd_soc_dapm_widget *w;
673 			struct snd_soc_dai *cpu_dai;
674 			struct snd_sof_dev *sdev;
675 			struct snd_sof_dai *sdai;
676 
677 			rtd = snd_soc_substream_to_rtd(hext_stream->link_substream);
678 			cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
679 			w = snd_soc_dai_get_widget(cpu_dai, hdac_stream(hext_stream)->direction);
680 			swidget = w->dobj.private;
681 			sdev = widget_to_sdev(w);
682 			sdai = swidget->private;
683 			ops = sdai->platform_private;
684 
685 			if (rtd->dpcm[hext_stream->link_substream->stream].state !=
686 			    SND_SOC_DPCM_STATE_PAUSED)
687 				continue;
688 
689 			/* for consistency with TRIGGER_SUSPEND  */
690 			if (ops->post_trigger) {
691 				ret = ops->post_trigger(sdev, cpu_dai,
692 							hext_stream->link_substream,
693 							SNDRV_PCM_TRIGGER_SUSPEND);
694 				if (ret < 0)
695 					return ret;
696 			}
697 
698 			ret = hda_link_dma_cleanup(hext_stream->link_substream,
699 						   hext_stream, cpu_dai, true);
700 			if (ret < 0)
701 				return ret;
702 		}
703 	}
704 
705 	return 0;
706 }
707 
708 static void ssp_set_dai_drv_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *ops)
709 {
710 	const struct sof_intel_dsp_desc *chip;
711 	int i;
712 
713 	chip = get_chip_info(sdev->pdata);
714 
715 	if (chip->hw_ip_version >= SOF_INTEL_ACE_2_0) {
716 		for (i = 0; i < ops->num_drv; i++) {
717 			if (strstr(ops->drv[i].name, "SSP"))
718 				ops->drv[i].ops = &ssp_dai_ops;
719 		}
720 	}
721 }
722 
723 static void dmic_set_dai_drv_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *ops)
724 {
725 	const struct sof_intel_dsp_desc *chip;
726 	int i;
727 
728 	chip = get_chip_info(sdev->pdata);
729 
730 	if (chip->hw_ip_version >= SOF_INTEL_ACE_2_0) {
731 		for (i = 0; i < ops->num_drv; i++) {
732 			if (strstr(ops->drv[i].name, "DMIC"))
733 				ops->drv[i].ops = &dmic_dai_ops;
734 		}
735 	}
736 }
737 
738 #else
739 
740 static inline void ssp_set_dai_drv_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *ops) {}
741 static inline void dmic_set_dai_drv_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *ops) {}
742 
743 #endif /* CONFIG_SND_SOC_SOF_HDA_LINK */
744 
745 void hda_set_dai_drv_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *ops)
746 {
747 	int i;
748 
749 	for (i = 0; i < ops->num_drv; i++) {
750 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC)
751 		if (strstr(ops->drv[i].name, "iDisp") ||
752 		    strstr(ops->drv[i].name, "Analog") ||
753 		    strstr(ops->drv[i].name, "Digital"))
754 			ops->drv[i].ops = &hda_dai_ops;
755 #endif
756 	}
757 
758 	ssp_set_dai_drv_ops(sdev, ops);
759 	dmic_set_dai_drv_ops(sdev, ops);
760 
761 	if (sdev->pdata->ipc_type == SOF_IPC_TYPE_4 && !hda_use_tplg_nhlt) {
762 		struct sof_ipc4_fw_data *ipc4_data = sdev->private;
763 
764 		ipc4_data->nhlt = intel_nhlt_init(sdev->dev);
765 	}
766 }
767 EXPORT_SYMBOL_NS(hda_set_dai_drv_ops, "SND_SOC_SOF_INTEL_HDA_COMMON");
768 
769 void hda_ops_free(struct snd_sof_dev *sdev)
770 {
771 	if (sdev->pdata->ipc_type == SOF_IPC_TYPE_4) {
772 		struct sof_ipc4_fw_data *ipc4_data = sdev->private;
773 
774 		if (!hda_use_tplg_nhlt)
775 			intel_nhlt_free(ipc4_data->nhlt);
776 
777 		kfree(sdev->private);
778 		sdev->private = NULL;
779 	}
780 }
781 EXPORT_SYMBOL_NS(hda_ops_free, "SND_SOC_SOF_INTEL_HDA_COMMON");
782 
783 /*
784  * common dai driver for skl+ platforms.
785  * some products who use this DAI array only physically have a subset of
786  * the DAIs, but no harm is done here by adding the whole set.
787  */
788 struct snd_soc_dai_driver skl_dai[] = {
789 {
790 	.name = "SSP0 Pin",
791 	.playback = {
792 		.channels_min = 1,
793 		.channels_max = 8,
794 	},
795 	.capture = {
796 		.channels_min = 1,
797 		.channels_max = 8,
798 	},
799 },
800 {
801 	.name = "SSP1 Pin",
802 	.playback = {
803 		.channels_min = 1,
804 		.channels_max = 8,
805 	},
806 	.capture = {
807 		.channels_min = 1,
808 		.channels_max = 8,
809 	},
810 },
811 {
812 	.name = "SSP2 Pin",
813 	.playback = {
814 		.channels_min = 1,
815 		.channels_max = 8,
816 	},
817 	.capture = {
818 		.channels_min = 1,
819 		.channels_max = 8,
820 	},
821 },
822 {
823 	.name = "SSP3 Pin",
824 	.playback = {
825 		.channels_min = 1,
826 		.channels_max = 8,
827 	},
828 	.capture = {
829 		.channels_min = 1,
830 		.channels_max = 8,
831 	},
832 },
833 {
834 	.name = "SSP4 Pin",
835 	.playback = {
836 		.channels_min = 1,
837 		.channels_max = 8,
838 	},
839 	.capture = {
840 		.channels_min = 1,
841 		.channels_max = 8,
842 	},
843 },
844 {
845 	.name = "SSP5 Pin",
846 	.playback = {
847 		.channels_min = 1,
848 		.channels_max = 8,
849 	},
850 	.capture = {
851 		.channels_min = 1,
852 		.channels_max = 8,
853 	},
854 },
855 {
856 	.name = "DMIC01 Pin",
857 	.capture = {
858 		.channels_min = 1,
859 		.channels_max = 4,
860 	},
861 },
862 {
863 	.name = "DMIC16k Pin",
864 	.capture = {
865 		.channels_min = 1,
866 		.channels_max = 4,
867 	},
868 },
869 {
870 	/* Virtual CPU DAI for Echo reference */
871 	.name = "Loopback Virtual Pin",
872 	.capture = {
873 		.channels_min = 1,
874 		.channels_max = 2,
875 	},
876 },
877 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC)
878 {
879 	.name = "iDisp1 Pin",
880 	.playback = {
881 		.channels_min = 1,
882 		.channels_max = 8,
883 	},
884 },
885 {
886 	.name = "iDisp2 Pin",
887 	.playback = {
888 		.channels_min = 1,
889 		.channels_max = 8,
890 	},
891 },
892 {
893 	.name = "iDisp3 Pin",
894 	.playback = {
895 		.channels_min = 1,
896 		.channels_max = 8,
897 	},
898 },
899 {
900 	.name = "iDisp4 Pin",
901 	.playback = {
902 		.channels_min = 1,
903 		.channels_max = 8,
904 	},
905 },
906 {
907 	.name = "Analog CPU DAI",
908 	.playback = {
909 		.channels_min = 1,
910 		.channels_max = 16,
911 	},
912 	.capture = {
913 		.channels_min = 1,
914 		.channels_max = 16,
915 	},
916 },
917 {
918 	.name = "Digital CPU DAI",
919 	.playback = {
920 		.channels_min = 1,
921 		.channels_max = 16,
922 	},
923 	.capture = {
924 		.channels_min = 1,
925 		.channels_max = 16,
926 	},
927 },
928 {
929 	.name = "Alt Analog CPU DAI",
930 	.playback = {
931 		.channels_min = 1,
932 		.channels_max = 16,
933 	},
934 	.capture = {
935 		.channels_min = 1,
936 		.channels_max = 16,
937 	},
938 },
939 #endif
940 };
941 EXPORT_SYMBOL_NS(skl_dai, "SND_SOC_SOF_INTEL_HDA_COMMON");
942 
943 int hda_dsp_dais_suspend(struct snd_sof_dev *sdev)
944 {
945 	/*
946 	 * In the corner case where a SUSPEND happens during a PAUSE, the ALSA core
947 	 * does not throw the TRIGGER_SUSPEND. This leaves the DAIs in an unbalanced state.
948 	 * Since the component suspend is called last, we can trap this corner case
949 	 * and force the DAIs to release their resources.
950 	 */
951 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_LINK)
952 	int ret;
953 
954 	ret = hda_dai_suspend(sof_to_bus(sdev));
955 	if (ret < 0)
956 		return ret;
957 #endif
958 
959 	return 0;
960 }
961