xref: /kernel/linux/linux-6.6/sound/soc/intel/avs/pcm.c (revision 62306a36)
1// SPDX-License-Identifier: GPL-2.0-only
2//
3// Copyright(c) 2021-2022 Intel Corporation. All rights reserved.
4//
5// Authors: Cezary Rojewski <cezary.rojewski@intel.com>
6//          Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com>
7//
8
9#include <linux/debugfs.h>
10#include <linux/device.h>
11#include <sound/hda_register.h>
12#include <sound/hdaudio_ext.h>
13#include <sound/pcm_params.h>
14#include <sound/soc-acpi.h>
15#include <sound/soc-acpi-intel-match.h>
16#include <sound/soc-component.h>
17#include "avs.h"
18#include "path.h"
19#include "topology.h"
20
21struct avs_dma_data {
22	struct avs_tplg_path_template *template;
23	struct avs_path *path;
24	/*
25	 * link stream is stored within substream's runtime
26	 * private_data to fulfill the needs of codec BE path
27	 *
28	 * host stream assigned
29	 */
30	struct hdac_ext_stream *host_stream;
31
32	struct snd_pcm_substream *substream;
33};
34
35static struct avs_tplg_path_template *
36avs_dai_find_path_template(struct snd_soc_dai *dai, bool is_fe, int direction)
37{
38	struct snd_soc_dapm_widget *dw = snd_soc_dai_get_widget(dai, direction);
39	struct snd_soc_dapm_path *dp;
40	enum snd_soc_dapm_direction dir;
41
42	if (direction == SNDRV_PCM_STREAM_CAPTURE) {
43		dir = is_fe ? SND_SOC_DAPM_DIR_OUT : SND_SOC_DAPM_DIR_IN;
44	} else {
45		dir = is_fe ? SND_SOC_DAPM_DIR_IN : SND_SOC_DAPM_DIR_OUT;
46	}
47
48	dp = list_first_entry_or_null(&dw->edges[dir], typeof(*dp), list_node[dir]);
49	if (!dp)
50		return NULL;
51
52	/* Get the other widget, with actual path template data */
53	dw = (dp->source == dw) ? dp->sink : dp->source;
54
55	return dw->priv;
56}
57
58static int avs_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai, bool is_fe,
59			   const struct snd_soc_dai_ops *ops)
60{
61	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
62	struct avs_dev *adev = to_avs_dev(dai->dev);
63	struct avs_tplg_path_template *template;
64	struct avs_dma_data *data;
65
66	template = avs_dai_find_path_template(dai, is_fe, substream->stream);
67	if (!template) {
68		dev_err(dai->dev, "no %s path for dai %s, invalid tplg?\n",
69			snd_pcm_stream_str(substream), dai->name);
70		return -EINVAL;
71	}
72
73	data = kzalloc(sizeof(*data), GFP_KERNEL);
74	if (!data)
75		return -ENOMEM;
76
77	data->substream = substream;
78	data->template = template;
79	snd_soc_dai_set_dma_data(dai, substream, data);
80
81	if (rtd->dai_link->ignore_suspend)
82		adev->num_lp_paths++;
83
84	return 0;
85}
86
87static int avs_dai_hw_params(struct snd_pcm_substream *substream,
88			     struct snd_pcm_hw_params *fe_hw_params,
89			     struct snd_pcm_hw_params *be_hw_params, struct snd_soc_dai *dai,
90			     int dma_id)
91{
92	struct avs_dma_data *data;
93	struct avs_path *path;
94	struct avs_dev *adev = to_avs_dev(dai->dev);
95	int ret;
96
97	data = snd_soc_dai_get_dma_data(dai, substream);
98
99	dev_dbg(dai->dev, "%s FE hw_params str %p rtd %p",
100		__func__, substream, substream->runtime);
101	dev_dbg(dai->dev, "rate %d chn %d vbd %d bd %d\n",
102		params_rate(fe_hw_params), params_channels(fe_hw_params),
103		params_width(fe_hw_params), params_physical_width(fe_hw_params));
104
105	dev_dbg(dai->dev, "%s BE hw_params str %p rtd %p",
106		__func__, substream, substream->runtime);
107	dev_dbg(dai->dev, "rate %d chn %d vbd %d bd %d\n",
108		params_rate(be_hw_params), params_channels(be_hw_params),
109		params_width(be_hw_params), params_physical_width(be_hw_params));
110
111	path = avs_path_create(adev, dma_id, data->template, fe_hw_params, be_hw_params);
112	if (IS_ERR(path)) {
113		ret = PTR_ERR(path);
114		dev_err(dai->dev, "create path failed: %d\n", ret);
115		return ret;
116	}
117
118	data->path = path;
119	return 0;
120}
121
122static int avs_dai_be_hw_params(struct snd_pcm_substream *substream,
123				struct snd_pcm_hw_params *be_hw_params, struct snd_soc_dai *dai,
124				int dma_id)
125{
126	struct snd_pcm_hw_params *fe_hw_params = NULL;
127	struct snd_soc_pcm_runtime *fe, *be;
128	struct snd_soc_dpcm *dpcm;
129
130	be = asoc_substream_to_rtd(substream);
131	for_each_dpcm_fe(be, substream->stream, dpcm) {
132		fe = dpcm->fe;
133		fe_hw_params = &fe->dpcm[substream->stream].hw_params;
134	}
135
136	return avs_dai_hw_params(substream, fe_hw_params, be_hw_params, dai, dma_id);
137}
138
139static int avs_dai_prepare(struct avs_dev *adev, struct snd_pcm_substream *substream,
140			   struct snd_soc_dai *dai)
141{
142	struct avs_dma_data *data;
143	int ret;
144
145	data = snd_soc_dai_get_dma_data(dai, substream);
146	if (!data->path)
147		return 0;
148
149	ret = avs_path_reset(data->path);
150	if (ret < 0) {
151		dev_err(dai->dev, "reset path failed: %d\n", ret);
152		return ret;
153	}
154
155	ret = avs_path_pause(data->path);
156	if (ret < 0)
157		dev_err(dai->dev, "pause path failed: %d\n", ret);
158	return ret;
159}
160
161static const struct snd_soc_dai_ops avs_dai_nonhda_be_ops;
162
163static int avs_dai_nonhda_be_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
164{
165	return avs_dai_startup(substream, dai, false, &avs_dai_nonhda_be_ops);
166}
167
168static void avs_dai_nonhda_be_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
169{
170	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
171	struct avs_dev *adev = to_avs_dev(dai->dev);
172	struct avs_dma_data *data;
173
174	if (rtd->dai_link->ignore_suspend)
175		adev->num_lp_paths--;
176
177	data = snd_soc_dai_get_dma_data(dai, substream);
178
179	snd_soc_dai_set_dma_data(dai, substream, NULL);
180	kfree(data);
181}
182
183static int avs_dai_nonhda_be_hw_params(struct snd_pcm_substream *substream,
184				       struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *dai)
185{
186	struct avs_dma_data *data;
187
188	data = snd_soc_dai_get_dma_data(dai, substream);
189	if (data->path)
190		return 0;
191
192	/* Actual port-id comes from topology. */
193	return avs_dai_be_hw_params(substream, hw_params, dai, 0);
194}
195
196static int avs_dai_nonhda_be_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
197{
198	struct avs_dma_data *data;
199
200	dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
201
202	data = snd_soc_dai_get_dma_data(dai, substream);
203	if (data->path) {
204		avs_path_free(data->path);
205		data->path = NULL;
206	}
207
208	return 0;
209}
210
211static int avs_dai_nonhda_be_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
212{
213	return avs_dai_prepare(to_avs_dev(dai->dev), substream, dai);
214}
215
216static int avs_dai_nonhda_be_trigger(struct snd_pcm_substream *substream, int cmd,
217				     struct snd_soc_dai *dai)
218{
219	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
220	struct avs_dma_data *data;
221	int ret = 0;
222
223	data = snd_soc_dai_get_dma_data(dai, substream);
224
225	switch (cmd) {
226	case SNDRV_PCM_TRIGGER_RESUME:
227		if (rtd->dai_link->ignore_suspend)
228			break;
229		fallthrough;
230	case SNDRV_PCM_TRIGGER_START:
231	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
232		ret = avs_path_pause(data->path);
233		if (ret < 0) {
234			dev_err(dai->dev, "pause BE path failed: %d\n", ret);
235			break;
236		}
237
238		ret = avs_path_run(data->path, AVS_TPLG_TRIGGER_AUTO);
239		if (ret < 0)
240			dev_err(dai->dev, "run BE path failed: %d\n", ret);
241		break;
242
243	case SNDRV_PCM_TRIGGER_SUSPEND:
244		if (rtd->dai_link->ignore_suspend)
245			break;
246		fallthrough;
247	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
248	case SNDRV_PCM_TRIGGER_STOP:
249		ret = avs_path_pause(data->path);
250		if (ret < 0)
251			dev_err(dai->dev, "pause BE path failed: %d\n", ret);
252
253		ret = avs_path_reset(data->path);
254		if (ret < 0)
255			dev_err(dai->dev, "reset BE path failed: %d\n", ret);
256		break;
257
258	default:
259		ret = -EINVAL;
260		break;
261	}
262
263	return ret;
264}
265
266static const struct snd_soc_dai_ops avs_dai_nonhda_be_ops = {
267	.startup = avs_dai_nonhda_be_startup,
268	.shutdown = avs_dai_nonhda_be_shutdown,
269	.hw_params = avs_dai_nonhda_be_hw_params,
270	.hw_free = avs_dai_nonhda_be_hw_free,
271	.prepare = avs_dai_nonhda_be_prepare,
272	.trigger = avs_dai_nonhda_be_trigger,
273};
274
275static const struct snd_soc_dai_ops avs_dai_hda_be_ops;
276
277static int avs_dai_hda_be_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
278{
279	return avs_dai_startup(substream, dai, false, &avs_dai_hda_be_ops);
280}
281
282static void avs_dai_hda_be_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
283{
284	return avs_dai_nonhda_be_shutdown(substream, dai);
285}
286
287static int avs_dai_hda_be_hw_params(struct snd_pcm_substream *substream,
288				    struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *dai)
289{
290	struct avs_dma_data *data;
291	struct hdac_ext_stream *link_stream;
292
293	data = snd_soc_dai_get_dma_data(dai, substream);
294	if (data->path)
295		return 0;
296
297	link_stream = substream->runtime->private_data;
298
299	return avs_dai_be_hw_params(substream, hw_params, dai,
300				    hdac_stream(link_stream)->stream_tag - 1);
301}
302
303static int avs_dai_hda_be_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
304{
305	struct avs_dma_data *data;
306	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
307	struct hdac_ext_stream *link_stream;
308	struct hdac_ext_link *link;
309	struct hda_codec *codec;
310
311	dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
312
313	data = snd_soc_dai_get_dma_data(dai, substream);
314	if (!data->path)
315		return 0;
316
317	link_stream = substream->runtime->private_data;
318	link_stream->link_prepared = false;
319	avs_path_free(data->path);
320	data->path = NULL;
321
322	/* clear link <-> stream mapping */
323	codec = dev_to_hda_codec(asoc_rtd_to_codec(rtd, 0)->dev);
324	link = snd_hdac_ext_bus_get_hlink_by_addr(&codec->bus->core, codec->core.addr);
325	if (!link)
326		return -EINVAL;
327
328	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
329		snd_hdac_ext_bus_link_clear_stream_id(link, hdac_stream(link_stream)->stream_tag);
330
331	return 0;
332}
333
334static int avs_dai_hda_be_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
335{
336	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
337	struct snd_pcm_runtime *runtime = substream->runtime;
338	struct hdac_ext_stream *link_stream = runtime->private_data;
339	struct hdac_ext_link *link;
340	struct hda_codec *codec;
341	struct hdac_bus *bus;
342	unsigned int format_val;
343	int ret;
344
345	if (link_stream->link_prepared)
346		return 0;
347
348	codec = dev_to_hda_codec(asoc_rtd_to_codec(rtd, 0)->dev);
349	bus = &codec->bus->core;
350	format_val = snd_hdac_calc_stream_format(runtime->rate, runtime->channels, runtime->format,
351						 runtime->sample_bits, 0);
352
353	snd_hdac_ext_stream_decouple(bus, link_stream, true);
354	snd_hdac_ext_stream_reset(link_stream);
355	snd_hdac_ext_stream_setup(link_stream, format_val);
356
357	link = snd_hdac_ext_bus_get_hlink_by_addr(bus, codec->core.addr);
358	if (!link)
359		return -EINVAL;
360
361	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
362		snd_hdac_ext_bus_link_set_stream_id(link, hdac_stream(link_stream)->stream_tag);
363
364	ret = avs_dai_prepare(to_avs_dev(dai->dev), substream, dai);
365	if (ret)
366		return ret;
367
368	link_stream->link_prepared = true;
369	return 0;
370}
371
372static int avs_dai_hda_be_trigger(struct snd_pcm_substream *substream, int cmd,
373				  struct snd_soc_dai *dai)
374{
375	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
376	struct hdac_ext_stream *link_stream;
377	struct avs_dma_data *data;
378	int ret = 0;
379
380	dev_dbg(dai->dev, "entry %s cmd=%d\n", __func__, cmd);
381
382	data = snd_soc_dai_get_dma_data(dai, substream);
383	link_stream = substream->runtime->private_data;
384
385	switch (cmd) {
386	case SNDRV_PCM_TRIGGER_RESUME:
387		if (rtd->dai_link->ignore_suspend)
388			break;
389		fallthrough;
390	case SNDRV_PCM_TRIGGER_START:
391	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
392		snd_hdac_ext_stream_start(link_stream);
393
394		ret = avs_path_pause(data->path);
395		if (ret < 0) {
396			dev_err(dai->dev, "pause BE path failed: %d\n", ret);
397			break;
398		}
399
400		ret = avs_path_run(data->path, AVS_TPLG_TRIGGER_AUTO);
401		if (ret < 0)
402			dev_err(dai->dev, "run BE path failed: %d\n", ret);
403		break;
404
405	case SNDRV_PCM_TRIGGER_SUSPEND:
406		if (rtd->dai_link->ignore_suspend)
407			break;
408		fallthrough;
409	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
410	case SNDRV_PCM_TRIGGER_STOP:
411		ret = avs_path_pause(data->path);
412		if (ret < 0)
413			dev_err(dai->dev, "pause BE path failed: %d\n", ret);
414
415		snd_hdac_ext_stream_clear(link_stream);
416
417		ret = avs_path_reset(data->path);
418		if (ret < 0)
419			dev_err(dai->dev, "reset BE path failed: %d\n", ret);
420		break;
421
422	default:
423		ret = -EINVAL;
424		break;
425	}
426
427	return ret;
428}
429
430static const struct snd_soc_dai_ops avs_dai_hda_be_ops = {
431	.startup = avs_dai_hda_be_startup,
432	.shutdown = avs_dai_hda_be_shutdown,
433	.hw_params = avs_dai_hda_be_hw_params,
434	.hw_free = avs_dai_hda_be_hw_free,
435	.prepare = avs_dai_hda_be_prepare,
436	.trigger = avs_dai_hda_be_trigger,
437};
438
439static const unsigned int rates[] = {
440	8000, 11025, 12000, 16000,
441	22050, 24000, 32000, 44100,
442	48000, 64000, 88200, 96000,
443	128000, 176400, 192000,
444};
445
446static const struct snd_pcm_hw_constraint_list hw_rates = {
447	.count = ARRAY_SIZE(rates),
448	.list = rates,
449	.mask = 0,
450};
451
452const struct snd_soc_dai_ops avs_dai_fe_ops;
453
454static int avs_dai_fe_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
455{
456	struct snd_pcm_runtime *runtime = substream->runtime;
457	struct avs_dma_data *data;
458	struct avs_dev *adev = to_avs_dev(dai->dev);
459	struct hdac_bus *bus = &adev->base.core;
460	struct hdac_ext_stream *host_stream;
461	int ret;
462
463	ret = avs_dai_startup(substream, dai, true, &avs_dai_fe_ops);
464	if (ret)
465		return ret;
466
467	data = snd_soc_dai_get_dma_data(dai, substream);
468
469	host_stream = snd_hdac_ext_stream_assign(bus, substream, HDAC_EXT_STREAM_TYPE_HOST);
470	if (!host_stream) {
471		ret = -EBUSY;
472		goto err;
473	}
474
475	data->host_stream = host_stream;
476	ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
477	if (ret < 0)
478		goto err;
479
480	/* avoid wrap-around with wall-clock */
481	ret = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_TIME, 20, 178000000);
482	if (ret < 0)
483		goto err;
484
485	ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_rates);
486	if (ret < 0)
487		goto err;
488
489	snd_pcm_set_sync(substream);
490
491	dev_dbg(dai->dev, "%s fe STARTUP tag %d str %p",
492		__func__, hdac_stream(host_stream)->stream_tag, substream);
493
494	return 0;
495
496err:
497	kfree(data);
498	return ret;
499}
500
501static void avs_dai_fe_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
502{
503	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
504	struct avs_dev *adev = to_avs_dev(dai->dev);
505	struct avs_dma_data *data;
506
507	if (rtd->dai_link->ignore_suspend)
508		adev->num_lp_paths--;
509
510	data = snd_soc_dai_get_dma_data(dai, substream);
511
512	snd_soc_dai_set_dma_data(dai, substream, NULL);
513	snd_hdac_ext_stream_release(data->host_stream, HDAC_EXT_STREAM_TYPE_HOST);
514	kfree(data);
515}
516
517static int avs_dai_fe_hw_params(struct snd_pcm_substream *substream,
518				struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *dai)
519{
520	struct snd_pcm_hw_params *be_hw_params = NULL;
521	struct snd_soc_pcm_runtime *fe, *be;
522	struct snd_soc_dpcm *dpcm;
523	struct avs_dma_data *data;
524	struct hdac_ext_stream *host_stream;
525	int ret;
526
527	data = snd_soc_dai_get_dma_data(dai, substream);
528	if (data->path)
529		return 0;
530
531	host_stream = data->host_stream;
532
533	hdac_stream(host_stream)->bufsize = 0;
534	hdac_stream(host_stream)->period_bytes = 0;
535	hdac_stream(host_stream)->format_val = 0;
536
537	fe = asoc_substream_to_rtd(substream);
538	for_each_dpcm_be(fe, substream->stream, dpcm) {
539		be = dpcm->be;
540		be_hw_params = &be->dpcm[substream->stream].hw_params;
541	}
542
543	ret = avs_dai_hw_params(substream, hw_params, be_hw_params, dai,
544				hdac_stream(host_stream)->stream_tag - 1);
545	if (ret)
546		goto create_err;
547
548	ret = avs_path_bind(data->path);
549	if (ret < 0) {
550		dev_err(dai->dev, "bind FE <-> BE failed: %d\n", ret);
551		goto bind_err;
552	}
553
554	return 0;
555
556bind_err:
557	avs_path_free(data->path);
558	data->path = NULL;
559create_err:
560	snd_pcm_lib_free_pages(substream);
561	return ret;
562}
563
564static int __avs_dai_fe_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
565{
566	struct avs_dma_data *data;
567	struct hdac_ext_stream *host_stream;
568	int ret;
569
570	dev_dbg(dai->dev, "%s fe HW_FREE str %p rtd %p",
571		__func__, substream, substream->runtime);
572
573	data = snd_soc_dai_get_dma_data(dai, substream);
574	if (!data->path)
575		return 0;
576
577	host_stream = data->host_stream;
578
579	ret = avs_path_unbind(data->path);
580	if (ret < 0)
581		dev_err(dai->dev, "unbind FE <-> BE failed: %d\n", ret);
582
583	avs_path_free(data->path);
584	data->path = NULL;
585	snd_hdac_stream_cleanup(hdac_stream(host_stream));
586	hdac_stream(host_stream)->prepared = false;
587
588	return ret;
589}
590
591static int avs_dai_fe_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
592{
593	int ret;
594
595	ret = __avs_dai_fe_hw_free(substream, dai);
596	snd_pcm_lib_free_pages(substream);
597
598	return ret;
599}
600
601static int avs_dai_fe_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
602{
603	struct snd_pcm_runtime *runtime = substream->runtime;
604	struct avs_dma_data *data;
605	struct avs_dev *adev = to_avs_dev(dai->dev);
606	struct hdac_ext_stream *host_stream;
607	struct hdac_bus *bus;
608	unsigned int format_val;
609	int ret;
610
611	data = snd_soc_dai_get_dma_data(dai, substream);
612	host_stream = data->host_stream;
613
614	if (hdac_stream(host_stream)->prepared)
615		return 0;
616
617	bus = hdac_stream(host_stream)->bus;
618	snd_hdac_ext_stream_decouple(bus, data->host_stream, true);
619	snd_hdac_stream_reset(hdac_stream(host_stream));
620
621	format_val = snd_hdac_calc_stream_format(runtime->rate, runtime->channels, runtime->format,
622						 runtime->sample_bits, 0);
623
624	ret = snd_hdac_stream_set_params(hdac_stream(host_stream), format_val);
625	if (ret < 0)
626		return ret;
627
628	ret = snd_hdac_stream_setup(hdac_stream(host_stream));
629	if (ret < 0)
630		return ret;
631
632	ret = avs_dai_prepare(adev, substream, dai);
633	if (ret)
634		return ret;
635
636	hdac_stream(host_stream)->prepared = true;
637	return 0;
638}
639
640static int avs_dai_fe_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai)
641{
642	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
643	struct avs_dma_data *data;
644	struct hdac_ext_stream *host_stream;
645	struct hdac_bus *bus;
646	unsigned long flags;
647	int ret = 0;
648
649	data = snd_soc_dai_get_dma_data(dai, substream);
650	host_stream = data->host_stream;
651	bus = hdac_stream(host_stream)->bus;
652
653	switch (cmd) {
654	case SNDRV_PCM_TRIGGER_RESUME:
655		if (rtd->dai_link->ignore_suspend)
656			break;
657		fallthrough;
658	case SNDRV_PCM_TRIGGER_START:
659	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
660		spin_lock_irqsave(&bus->reg_lock, flags);
661		snd_hdac_stream_start(hdac_stream(host_stream));
662		spin_unlock_irqrestore(&bus->reg_lock, flags);
663
664		/* Timeout on DRSM poll shall not stop the resume so ignore the result. */
665		if (cmd == SNDRV_PCM_TRIGGER_RESUME)
666			snd_hdac_stream_wait_drsm(hdac_stream(host_stream));
667
668		ret = avs_path_pause(data->path);
669		if (ret < 0) {
670			dev_err(dai->dev, "pause FE path failed: %d\n", ret);
671			break;
672		}
673
674		ret = avs_path_run(data->path, AVS_TPLG_TRIGGER_AUTO);
675		if (ret < 0)
676			dev_err(dai->dev, "run FE path failed: %d\n", ret);
677
678		break;
679
680	case SNDRV_PCM_TRIGGER_SUSPEND:
681		if (rtd->dai_link->ignore_suspend)
682			break;
683		fallthrough;
684	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
685	case SNDRV_PCM_TRIGGER_STOP:
686		ret = avs_path_pause(data->path);
687		if (ret < 0)
688			dev_err(dai->dev, "pause FE path failed: %d\n", ret);
689
690		spin_lock_irqsave(&bus->reg_lock, flags);
691		snd_hdac_stream_stop(hdac_stream(host_stream));
692		spin_unlock_irqrestore(&bus->reg_lock, flags);
693
694		ret = avs_path_reset(data->path);
695		if (ret < 0)
696			dev_err(dai->dev, "reset FE path failed: %d\n", ret);
697		break;
698
699	default:
700		ret = -EINVAL;
701		break;
702	}
703
704	return ret;
705}
706
707const struct snd_soc_dai_ops avs_dai_fe_ops = {
708	.startup = avs_dai_fe_startup,
709	.shutdown = avs_dai_fe_shutdown,
710	.hw_params = avs_dai_fe_hw_params,
711	.hw_free = avs_dai_fe_hw_free,
712	.prepare = avs_dai_fe_prepare,
713	.trigger = avs_dai_fe_trigger,
714};
715
716static ssize_t topology_name_read(struct file *file, char __user *user_buf, size_t count,
717				  loff_t *ppos)
718{
719	struct snd_soc_component *component = file->private_data;
720	struct snd_soc_card *card = component->card;
721	struct snd_soc_acpi_mach *mach = dev_get_platdata(card->dev);
722	char buf[64];
723	size_t len;
724
725	len = scnprintf(buf, sizeof(buf), "%s/%s\n", component->driver->topology_name_prefix,
726			mach->tplg_filename);
727
728	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
729}
730
731static const struct file_operations topology_name_fops = {
732	.open = simple_open,
733	.read = topology_name_read,
734	.llseek = default_llseek,
735};
736
737static int avs_component_load_libraries(struct avs_soc_component *acomp)
738{
739	struct avs_tplg *tplg = acomp->tplg;
740	struct avs_dev *adev = to_avs_dev(acomp->base.dev);
741	int ret;
742
743	if (!tplg->num_libs)
744		return 0;
745
746	/* Parent device may be asleep and library loading involves IPCs. */
747	ret = pm_runtime_resume_and_get(adev->dev);
748	if (ret < 0)
749		return ret;
750
751	avs_hda_power_gating_enable(adev, false);
752	avs_hda_clock_gating_enable(adev, false);
753	avs_hda_l1sen_enable(adev, false);
754
755	ret = avs_dsp_load_libraries(adev, tplg->libs, tplg->num_libs);
756
757	avs_hda_l1sen_enable(adev, true);
758	avs_hda_clock_gating_enable(adev, true);
759	avs_hda_power_gating_enable(adev, true);
760
761	if (!ret)
762		ret = avs_module_info_init(adev, false);
763
764	pm_runtime_mark_last_busy(adev->dev);
765	pm_runtime_put_autosuspend(adev->dev);
766
767	return ret;
768}
769
770static int avs_component_probe(struct snd_soc_component *component)
771{
772	struct snd_soc_card *card = component->card;
773	struct snd_soc_acpi_mach *mach;
774	struct avs_soc_component *acomp;
775	struct avs_dev *adev;
776	char *filename;
777	int ret;
778
779	dev_dbg(card->dev, "probing %s card %s\n", component->name, card->name);
780	mach = dev_get_platdata(card->dev);
781	acomp = to_avs_soc_component(component);
782	adev = to_avs_dev(component->dev);
783
784	acomp->tplg = avs_tplg_new(component);
785	if (!acomp->tplg)
786		return -ENOMEM;
787
788	if (!mach->tplg_filename)
789		goto finalize;
790
791	/* Load specified topology and create debugfs for it. */
792	filename = kasprintf(GFP_KERNEL, "%s/%s", component->driver->topology_name_prefix,
793			     mach->tplg_filename);
794	if (!filename)
795		return -ENOMEM;
796
797	ret = avs_load_topology(component, filename);
798	kfree(filename);
799	if (ret == -ENOENT && !strncmp(mach->tplg_filename, "hda-", 4)) {
800		unsigned int vendor_id;
801
802		if (sscanf(mach->tplg_filename, "hda-%08x-tplg.bin", &vendor_id) != 1)
803			return ret;
804
805		if (((vendor_id >> 16) & 0xFFFF) == 0x8086)
806			mach->tplg_filename = devm_kasprintf(adev->dev, GFP_KERNEL,
807							     "hda-8086-generic-tplg.bin");
808		else
809			mach->tplg_filename = devm_kasprintf(adev->dev, GFP_KERNEL,
810							     "hda-generic-tplg.bin");
811
812		filename = kasprintf(GFP_KERNEL, "%s/%s", component->driver->topology_name_prefix,
813				     mach->tplg_filename);
814		if (!filename)
815			return -ENOMEM;
816
817		dev_info(card->dev, "trying to load fallback topology %s\n", mach->tplg_filename);
818		ret = avs_load_topology(component, filename);
819		kfree(filename);
820	}
821	if (ret < 0)
822		return ret;
823
824	ret = avs_component_load_libraries(acomp);
825	if (ret < 0) {
826		dev_err(card->dev, "libraries loading failed: %d\n", ret);
827		goto err_load_libs;
828	}
829
830finalize:
831	debugfs_create_file("topology_name", 0444, component->debugfs_root, component,
832			    &topology_name_fops);
833
834	mutex_lock(&adev->comp_list_mutex);
835	list_add_tail(&acomp->node, &adev->comp_list);
836	mutex_unlock(&adev->comp_list_mutex);
837
838	return 0;
839
840err_load_libs:
841	avs_remove_topology(component);
842	return ret;
843}
844
845static void avs_component_remove(struct snd_soc_component *component)
846{
847	struct avs_soc_component *acomp = to_avs_soc_component(component);
848	struct snd_soc_acpi_mach *mach;
849	struct avs_dev *adev = to_avs_dev(component->dev);
850	int ret;
851
852	mach = dev_get_platdata(component->card->dev);
853
854	mutex_lock(&adev->comp_list_mutex);
855	list_del(&acomp->node);
856	mutex_unlock(&adev->comp_list_mutex);
857
858	if (mach->tplg_filename) {
859		ret = avs_remove_topology(component);
860		if (ret < 0)
861			dev_err(component->dev, "unload topology failed: %d\n", ret);
862	}
863}
864
865static int avs_dai_resume_hw_params(struct snd_soc_dai *dai, struct avs_dma_data *data)
866{
867	struct snd_pcm_substream *substream;
868	struct snd_soc_pcm_runtime *rtd;
869	int ret;
870
871	substream = data->substream;
872	rtd = asoc_substream_to_rtd(substream);
873
874	ret = dai->driver->ops->hw_params(substream, &rtd->dpcm[substream->stream].hw_params, dai);
875	if (ret)
876		dev_err(dai->dev, "hw_params on resume failed: %d\n", ret);
877
878	return ret;
879}
880
881static int avs_dai_resume_fe_prepare(struct snd_soc_dai *dai, struct avs_dma_data *data)
882{
883	struct hdac_ext_stream *host_stream;
884	struct hdac_stream *hstream;
885	struct hdac_bus *bus;
886	int ret;
887
888	host_stream = data->host_stream;
889	hstream = hdac_stream(host_stream);
890	bus = hdac_stream(host_stream)->bus;
891
892	/* Set DRSM before programming stream and position registers. */
893	snd_hdac_stream_drsm_enable(bus, true, hstream->index);
894
895	ret = dai->driver->ops->prepare(data->substream, dai);
896	if (ret) {
897		dev_err(dai->dev, "prepare FE on resume failed: %d\n", ret);
898		return ret;
899	}
900
901	writel(host_stream->pphcllpl, host_stream->pphc_addr + AZX_REG_PPHCLLPL);
902	writel(host_stream->pphcllpu, host_stream->pphc_addr + AZX_REG_PPHCLLPU);
903	writel(host_stream->pphcldpl, host_stream->pphc_addr + AZX_REG_PPHCLDPL);
904	writel(host_stream->pphcldpu, host_stream->pphc_addr + AZX_REG_PPHCLDPU);
905
906	/* As per HW spec recommendation, program LPIB and DPIB to the same value. */
907	snd_hdac_stream_set_lpib(hstream, hstream->lpib);
908	snd_hdac_stream_set_dpibr(bus, hstream, hstream->lpib);
909
910	return 0;
911}
912
913static int avs_dai_resume_be_prepare(struct snd_soc_dai *dai, struct avs_dma_data *data)
914{
915	int ret;
916
917	ret = dai->driver->ops->prepare(data->substream, dai);
918	if (ret)
919		dev_err(dai->dev, "prepare BE on resume failed: %d\n", ret);
920
921	return ret;
922}
923
924static int avs_dai_suspend_fe_hw_free(struct snd_soc_dai *dai, struct avs_dma_data *data)
925{
926	struct hdac_ext_stream *host_stream;
927	int ret;
928
929	host_stream = data->host_stream;
930
931	/* Store position addresses so we can resume from them later on. */
932	hdac_stream(host_stream)->lpib = snd_hdac_stream_get_pos_lpib(hdac_stream(host_stream));
933	host_stream->pphcllpl = readl(host_stream->pphc_addr + AZX_REG_PPHCLLPL);
934	host_stream->pphcllpu = readl(host_stream->pphc_addr + AZX_REG_PPHCLLPU);
935	host_stream->pphcldpl = readl(host_stream->pphc_addr + AZX_REG_PPHCLDPL);
936	host_stream->pphcldpu = readl(host_stream->pphc_addr + AZX_REG_PPHCLDPU);
937
938	ret = __avs_dai_fe_hw_free(data->substream, dai);
939	if (ret < 0)
940		dev_err(dai->dev, "hw_free FE on suspend failed: %d\n", ret);
941
942	return ret;
943}
944
945static int avs_dai_suspend_be_hw_free(struct snd_soc_dai *dai, struct avs_dma_data *data)
946{
947	int ret;
948
949	ret = dai->driver->ops->hw_free(data->substream, dai);
950	if (ret < 0)
951		dev_err(dai->dev, "hw_free BE on suspend failed: %d\n", ret);
952
953	return ret;
954}
955
956static int avs_component_pm_op(struct snd_soc_component *component, bool be,
957			       int (*op)(struct snd_soc_dai *, struct avs_dma_data *))
958{
959	struct snd_soc_pcm_runtime *rtd;
960	struct avs_dma_data *data;
961	struct snd_soc_dai *dai;
962	int ret;
963
964	for_each_component_dais(component, dai) {
965		data = snd_soc_dai_dma_data_get_playback(dai);
966		if (data) {
967			rtd = asoc_substream_to_rtd(data->substream);
968			if (rtd->dai_link->no_pcm == be && !rtd->dai_link->ignore_suspend) {
969				ret = op(dai, data);
970				if (ret < 0) {
971					__snd_pcm_set_state(data->substream->runtime,
972							    SNDRV_PCM_STATE_DISCONNECTED);
973					return ret;
974				}
975			}
976		}
977
978		data = snd_soc_dai_dma_data_get_capture(dai);
979		if (data) {
980			rtd = asoc_substream_to_rtd(data->substream);
981			if (rtd->dai_link->no_pcm == be && !rtd->dai_link->ignore_suspend) {
982				ret = op(dai, data);
983				if (ret < 0) {
984					__snd_pcm_set_state(data->substream->runtime,
985							    SNDRV_PCM_STATE_DISCONNECTED);
986					return ret;
987				}
988			}
989		}
990	}
991
992	return 0;
993}
994
995static int avs_component_resume_hw_params(struct snd_soc_component *component, bool be)
996{
997	return avs_component_pm_op(component, be, &avs_dai_resume_hw_params);
998}
999
1000static int avs_component_resume_prepare(struct snd_soc_component *component, bool be)
1001{
1002	int (*prepare_cb)(struct snd_soc_dai *dai, struct avs_dma_data *data);
1003
1004	if (be)
1005		prepare_cb = &avs_dai_resume_be_prepare;
1006	else
1007		prepare_cb = &avs_dai_resume_fe_prepare;
1008
1009	return avs_component_pm_op(component, be, prepare_cb);
1010}
1011
1012static int avs_component_suspend_hw_free(struct snd_soc_component *component, bool be)
1013{
1014	int (*hw_free_cb)(struct snd_soc_dai *dai, struct avs_dma_data *data);
1015
1016	if (be)
1017		hw_free_cb = &avs_dai_suspend_be_hw_free;
1018	else
1019		hw_free_cb = &avs_dai_suspend_fe_hw_free;
1020
1021	return avs_component_pm_op(component, be, hw_free_cb);
1022}
1023
1024static int avs_component_suspend(struct snd_soc_component *component)
1025{
1026	int ret;
1027
1028	/*
1029	 * When freeing paths, FEs need to be first as they perform
1030	 * path unbinding.
1031	 */
1032	ret = avs_component_suspend_hw_free(component, false);
1033	if (ret)
1034		return ret;
1035
1036	return avs_component_suspend_hw_free(component, true);
1037}
1038
1039static int avs_component_resume(struct snd_soc_component *component)
1040{
1041	int ret;
1042
1043	/*
1044	 * When creating paths, FEs need to be last as they perform
1045	 * path binding.
1046	 */
1047	ret = avs_component_resume_hw_params(component, true);
1048	if (ret)
1049		return ret;
1050
1051	ret = avs_component_resume_hw_params(component, false);
1052	if (ret)
1053		return ret;
1054
1055	/* It is expected that the LINK stream is prepared first. */
1056	ret = avs_component_resume_prepare(component, true);
1057	if (ret)
1058		return ret;
1059
1060	return avs_component_resume_prepare(component, false);
1061}
1062
1063static const struct snd_pcm_hardware avs_pcm_hardware = {
1064	.info			= SNDRV_PCM_INFO_MMAP |
1065				  SNDRV_PCM_INFO_MMAP_VALID |
1066				  SNDRV_PCM_INFO_INTERLEAVED |
1067				  SNDRV_PCM_INFO_PAUSE |
1068				  SNDRV_PCM_INFO_RESUME |
1069				  SNDRV_PCM_INFO_NO_PERIOD_WAKEUP,
1070	.formats		= SNDRV_PCM_FMTBIT_S16_LE |
1071				  SNDRV_PCM_FMTBIT_S24_LE |
1072				  SNDRV_PCM_FMTBIT_S32_LE,
1073	.buffer_bytes_max	= AZX_MAX_BUF_SIZE,
1074	.period_bytes_min	= 128,
1075	.period_bytes_max	= AZX_MAX_BUF_SIZE / 2,
1076	.periods_min		= 2,
1077	.periods_max		= AZX_MAX_FRAG,
1078	.fifo_size		= 0,
1079};
1080
1081static int avs_component_open(struct snd_soc_component *component,
1082			      struct snd_pcm_substream *substream)
1083{
1084	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
1085
1086	/* only FE DAI links are handled here */
1087	if (rtd->dai_link->no_pcm)
1088		return 0;
1089
1090	return snd_soc_set_runtime_hwparams(substream, &avs_pcm_hardware);
1091}
1092
1093static unsigned int avs_hda_stream_dpib_read(struct hdac_ext_stream *stream)
1094{
1095	return readl(hdac_stream(stream)->bus->remap_addr + AZX_REG_VS_SDXDPIB_XBASE +
1096		     (AZX_REG_VS_SDXDPIB_XINTERVAL * hdac_stream(stream)->index));
1097}
1098
1099static snd_pcm_uframes_t
1100avs_component_pointer(struct snd_soc_component *component, struct snd_pcm_substream *substream)
1101{
1102	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
1103	struct avs_dma_data *data;
1104	struct hdac_ext_stream *host_stream;
1105	unsigned int pos;
1106
1107	data = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream);
1108	if (!data->host_stream)
1109		return 0;
1110
1111	host_stream = data->host_stream;
1112	pos = avs_hda_stream_dpib_read(host_stream);
1113
1114	if (pos >= hdac_stream(host_stream)->bufsize)
1115		pos = 0;
1116
1117	return bytes_to_frames(substream->runtime, pos);
1118}
1119
1120static int avs_component_mmap(struct snd_soc_component *component,
1121			      struct snd_pcm_substream *substream,
1122			      struct vm_area_struct *vma)
1123{
1124	return snd_pcm_lib_default_mmap(substream, vma);
1125}
1126
1127#define MAX_PREALLOC_SIZE	(32 * 1024 * 1024)
1128
1129static int avs_component_construct(struct snd_soc_component *component,
1130				   struct snd_soc_pcm_runtime *rtd)
1131{
1132	struct snd_soc_dai *dai = asoc_rtd_to_cpu(rtd, 0);
1133	struct snd_pcm *pcm = rtd->pcm;
1134
1135	if (dai->driver->playback.channels_min)
1136		snd_pcm_set_managed_buffer(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream,
1137					   SNDRV_DMA_TYPE_DEV_SG, component->dev, 0,
1138					   MAX_PREALLOC_SIZE);
1139
1140	if (dai->driver->capture.channels_min)
1141		snd_pcm_set_managed_buffer(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
1142					   SNDRV_DMA_TYPE_DEV_SG, component->dev, 0,
1143					   MAX_PREALLOC_SIZE);
1144
1145	return 0;
1146}
1147
1148static const struct snd_soc_component_driver avs_component_driver = {
1149	.name			= "avs-pcm",
1150	.probe			= avs_component_probe,
1151	.remove			= avs_component_remove,
1152	.suspend		= avs_component_suspend,
1153	.resume			= avs_component_resume,
1154	.open			= avs_component_open,
1155	.pointer		= avs_component_pointer,
1156	.mmap			= avs_component_mmap,
1157	.pcm_construct		= avs_component_construct,
1158	.module_get_upon_open	= 1, /* increment refcount when a pcm is opened */
1159	.topology_name_prefix	= "intel/avs",
1160};
1161
1162int avs_soc_component_register(struct device *dev, const char *name,
1163			       const struct snd_soc_component_driver *drv,
1164			       struct snd_soc_dai_driver *cpu_dais, int num_cpu_dais)
1165{
1166	struct avs_soc_component *acomp;
1167	int ret;
1168
1169	acomp = devm_kzalloc(dev, sizeof(*acomp), GFP_KERNEL);
1170	if (!acomp)
1171		return -ENOMEM;
1172
1173	ret = snd_soc_component_initialize(&acomp->base, drv, dev);
1174	if (ret < 0)
1175		return ret;
1176
1177	/* force name change after ASoC is done with its init */
1178	acomp->base.name = name;
1179	INIT_LIST_HEAD(&acomp->node);
1180
1181	return snd_soc_add_component(&acomp->base, cpu_dais, num_cpu_dais);
1182}
1183
1184static struct snd_soc_dai_driver dmic_cpu_dais[] = {
1185{
1186	.name = "DMIC Pin",
1187	.ops = &avs_dai_nonhda_be_ops,
1188	.capture = {
1189		.stream_name	= "DMIC Rx",
1190		.channels_min	= 1,
1191		.channels_max	= 4,
1192		.rates		= SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_48000,
1193		.formats	= SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
1194	},
1195},
1196{
1197	.name = "DMIC WoV Pin",
1198	.ops = &avs_dai_nonhda_be_ops,
1199	.capture = {
1200		.stream_name	= "DMIC WoV Rx",
1201		.channels_min	= 1,
1202		.channels_max	= 4,
1203		.rates		= SNDRV_PCM_RATE_16000,
1204		.formats	= SNDRV_PCM_FMTBIT_S16_LE,
1205	},
1206},
1207};
1208
1209int avs_dmic_platform_register(struct avs_dev *adev, const char *name)
1210{
1211	return avs_soc_component_register(adev->dev, name, &avs_component_driver, dmic_cpu_dais,
1212					  ARRAY_SIZE(dmic_cpu_dais));
1213}
1214
1215static const struct snd_soc_dai_driver i2s_dai_template = {
1216	.ops = &avs_dai_nonhda_be_ops,
1217	.playback = {
1218		.channels_min	= 1,
1219		.channels_max	= 8,
1220		.rates		= SNDRV_PCM_RATE_8000_192000 |
1221				  SNDRV_PCM_RATE_KNOT,
1222		.formats	= SNDRV_PCM_FMTBIT_S16_LE |
1223				  SNDRV_PCM_FMTBIT_S24_LE |
1224				  SNDRV_PCM_FMTBIT_S32_LE,
1225	},
1226	.capture = {
1227		.channels_min	= 1,
1228		.channels_max	= 8,
1229		.rates		= SNDRV_PCM_RATE_8000_192000 |
1230				  SNDRV_PCM_RATE_KNOT,
1231		.formats	= SNDRV_PCM_FMTBIT_S16_LE |
1232				  SNDRV_PCM_FMTBIT_S24_LE |
1233				  SNDRV_PCM_FMTBIT_S32_LE,
1234	},
1235};
1236
1237int avs_i2s_platform_register(struct avs_dev *adev, const char *name, unsigned long port_mask,
1238			      unsigned long *tdms)
1239{
1240	struct snd_soc_dai_driver *cpus, *dai;
1241	size_t ssp_count, cpu_count;
1242	int i, j;
1243
1244	ssp_count = adev->hw_cfg.i2s_caps.ctrl_count;
1245	cpu_count = hweight_long(port_mask);
1246	if (tdms)
1247		for_each_set_bit(i, &port_mask, ssp_count)
1248			cpu_count += hweight_long(tdms[i]);
1249
1250	cpus = devm_kzalloc(adev->dev, sizeof(*cpus) * cpu_count, GFP_KERNEL);
1251	if (!cpus)
1252		return -ENOMEM;
1253
1254	dai = cpus;
1255	for_each_set_bit(i, &port_mask, ssp_count) {
1256		memcpy(dai, &i2s_dai_template, sizeof(*dai));
1257
1258		dai->name =
1259			devm_kasprintf(adev->dev, GFP_KERNEL, "SSP%d Pin", i);
1260		dai->playback.stream_name =
1261			devm_kasprintf(adev->dev, GFP_KERNEL, "ssp%d Tx", i);
1262		dai->capture.stream_name =
1263			devm_kasprintf(adev->dev, GFP_KERNEL, "ssp%d Rx", i);
1264
1265		if (!dai->name || !dai->playback.stream_name || !dai->capture.stream_name)
1266			return -ENOMEM;
1267		dai++;
1268	}
1269
1270	if (!tdms)
1271		goto plat_register;
1272
1273	for_each_set_bit(i, &port_mask, ssp_count) {
1274		for_each_set_bit(j, &tdms[i], ssp_count) {
1275			memcpy(dai, &i2s_dai_template, sizeof(*dai));
1276
1277			dai->name =
1278				devm_kasprintf(adev->dev, GFP_KERNEL, "SSP%d:%d Pin", i, j);
1279			dai->playback.stream_name =
1280				devm_kasprintf(adev->dev, GFP_KERNEL, "ssp%d:%d Tx", i, j);
1281			dai->capture.stream_name =
1282				devm_kasprintf(adev->dev, GFP_KERNEL, "ssp%d:%d Rx", i, j);
1283
1284			if (!dai->name || !dai->playback.stream_name || !dai->capture.stream_name)
1285				return -ENOMEM;
1286			dai++;
1287		}
1288	}
1289
1290plat_register:
1291	return avs_soc_component_register(adev->dev, name, &avs_component_driver, cpus, cpu_count);
1292}
1293
1294/* HD-Audio CPU DAI template */
1295static const struct snd_soc_dai_driver hda_cpu_dai = {
1296	.ops = &avs_dai_hda_be_ops,
1297	.playback = {
1298		.channels_min	= 1,
1299		.channels_max	= 8,
1300		.rates		= SNDRV_PCM_RATE_8000_192000,
1301		.formats	= SNDRV_PCM_FMTBIT_S16_LE |
1302				  SNDRV_PCM_FMTBIT_S24_LE |
1303				  SNDRV_PCM_FMTBIT_S32_LE,
1304	},
1305	.capture = {
1306		.channels_min	= 1,
1307		.channels_max	= 8,
1308		.rates		= SNDRV_PCM_RATE_8000_192000,
1309		.formats	= SNDRV_PCM_FMTBIT_S16_LE |
1310				  SNDRV_PCM_FMTBIT_S24_LE |
1311				  SNDRV_PCM_FMTBIT_S32_LE,
1312	},
1313};
1314
1315static void avs_component_hda_unregister_dais(struct snd_soc_component *component)
1316{
1317	struct snd_soc_acpi_mach *mach;
1318	struct snd_soc_dai *dai, *save;
1319	struct hda_codec *codec;
1320	char name[32];
1321
1322	mach = dev_get_platdata(component->card->dev);
1323	codec = mach->pdata;
1324	sprintf(name, "%s-cpu", dev_name(&codec->core.dev));
1325
1326	for_each_component_dais_safe(component, dai, save) {
1327		int stream;
1328
1329		if (!strstr(dai->driver->name, name))
1330			continue;
1331
1332		for_each_pcm_streams(stream)
1333			snd_soc_dapm_free_widget(snd_soc_dai_get_widget(dai, stream));
1334
1335		snd_soc_unregister_dai(dai);
1336	}
1337}
1338
1339static int avs_component_hda_probe(struct snd_soc_component *component)
1340{
1341	struct snd_soc_dapm_context *dapm;
1342	struct snd_soc_dai_driver *dais;
1343	struct snd_soc_acpi_mach *mach;
1344	struct hda_codec *codec;
1345	struct hda_pcm *pcm;
1346	const char *cname;
1347	int pcm_count = 0, ret, i;
1348
1349	mach = dev_get_platdata(component->card->dev);
1350	if (!mach)
1351		return -EINVAL;
1352
1353	codec = mach->pdata;
1354	if (list_empty(&codec->pcm_list_head))
1355		return -EINVAL;
1356	list_for_each_entry(pcm, &codec->pcm_list_head, list)
1357		pcm_count++;
1358
1359	dais = devm_kcalloc(component->dev, pcm_count, sizeof(*dais),
1360			    GFP_KERNEL);
1361	if (!dais)
1362		return -ENOMEM;
1363
1364	cname = dev_name(&codec->core.dev);
1365	dapm = snd_soc_component_get_dapm(component);
1366	pcm = list_first_entry(&codec->pcm_list_head, struct hda_pcm, list);
1367
1368	for (i = 0; i < pcm_count; i++, pcm = list_next_entry(pcm, list)) {
1369		struct snd_soc_dai *dai;
1370
1371		memcpy(&dais[i], &hda_cpu_dai, sizeof(*dais));
1372		dais[i].id = i;
1373		dais[i].name = devm_kasprintf(component->dev, GFP_KERNEL,
1374					      "%s-cpu%d", cname, i);
1375		if (!dais[i].name) {
1376			ret = -ENOMEM;
1377			goto exit;
1378		}
1379
1380		if (pcm->stream[0].substreams) {
1381			dais[i].playback.stream_name =
1382				devm_kasprintf(component->dev, GFP_KERNEL,
1383					       "%s-cpu%d Tx", cname, i);
1384			if (!dais[i].playback.stream_name) {
1385				ret = -ENOMEM;
1386				goto exit;
1387			}
1388		}
1389
1390		if (pcm->stream[1].substreams) {
1391			dais[i].capture.stream_name =
1392				devm_kasprintf(component->dev, GFP_KERNEL,
1393					       "%s-cpu%d Rx", cname, i);
1394			if (!dais[i].capture.stream_name) {
1395				ret = -ENOMEM;
1396				goto exit;
1397			}
1398		}
1399
1400		dai = snd_soc_register_dai(component, &dais[i], false);
1401		if (!dai) {
1402			dev_err(component->dev, "register dai for %s failed\n",
1403				pcm->name);
1404			ret = -EINVAL;
1405			goto exit;
1406		}
1407
1408		ret = snd_soc_dapm_new_dai_widgets(dapm, dai);
1409		if (ret < 0) {
1410			dev_err(component->dev, "create widgets failed: %d\n",
1411				ret);
1412			goto exit;
1413		}
1414	}
1415
1416	ret = avs_component_probe(component);
1417exit:
1418	if (ret)
1419		avs_component_hda_unregister_dais(component);
1420
1421	return ret;
1422}
1423
1424static void avs_component_hda_remove(struct snd_soc_component *component)
1425{
1426	avs_component_hda_unregister_dais(component);
1427	avs_component_remove(component);
1428}
1429
1430static int avs_component_hda_open(struct snd_soc_component *component,
1431				  struct snd_pcm_substream *substream)
1432{
1433	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
1434	struct hdac_ext_stream *link_stream;
1435	struct hda_codec *codec;
1436
1437	if (!rtd->dai_link->no_pcm) {
1438		struct snd_pcm_hardware hwparams = avs_pcm_hardware;
1439		struct snd_soc_pcm_runtime *be;
1440		struct snd_soc_dpcm *dpcm;
1441		int dir = substream->stream;
1442
1443		/*
1444		 * Support the DPCM reparenting while still fulfilling expectations of HDAudio
1445		 * common code - a valid stream pointer at substream->runtime->private_data -
1446		 * by having all FEs point to the same private data.
1447		 */
1448		for_each_dpcm_be(rtd, dir, dpcm) {
1449			struct snd_pcm_substream *be_substream;
1450
1451			be = dpcm->be;
1452			if (be->dpcm[dir].users == 1)
1453				break;
1454
1455			be_substream = snd_soc_dpcm_get_substream(be, dir);
1456			substream->runtime->private_data = be_substream->runtime->private_data;
1457			break;
1458		}
1459
1460		/* RESUME unsupported for de-coupled HD-Audio capture. */
1461		if (dir == SNDRV_PCM_STREAM_CAPTURE)
1462			hwparams.info &= ~SNDRV_PCM_INFO_RESUME;
1463
1464		return snd_soc_set_runtime_hwparams(substream, &hwparams);
1465	}
1466
1467	codec = dev_to_hda_codec(asoc_rtd_to_codec(rtd, 0)->dev);
1468	link_stream = snd_hdac_ext_stream_assign(&codec->bus->core, substream,
1469					     HDAC_EXT_STREAM_TYPE_LINK);
1470	if (!link_stream)
1471		return -EBUSY;
1472
1473	substream->runtime->private_data = link_stream;
1474	return 0;
1475}
1476
1477static int avs_component_hda_close(struct snd_soc_component *component,
1478				   struct snd_pcm_substream *substream)
1479{
1480	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
1481	struct hdac_ext_stream *link_stream;
1482
1483	/* only BE DAI links are handled here */
1484	if (!rtd->dai_link->no_pcm)
1485		return 0;
1486
1487	link_stream = substream->runtime->private_data;
1488	snd_hdac_ext_stream_release(link_stream, HDAC_EXT_STREAM_TYPE_LINK);
1489	substream->runtime->private_data = NULL;
1490
1491	return 0;
1492}
1493
1494static const struct snd_soc_component_driver avs_hda_component_driver = {
1495	.name			= "avs-hda-pcm",
1496	.probe			= avs_component_hda_probe,
1497	.remove			= avs_component_hda_remove,
1498	.suspend		= avs_component_suspend,
1499	.resume			= avs_component_resume,
1500	.open			= avs_component_hda_open,
1501	.close			= avs_component_hda_close,
1502	.pointer		= avs_component_pointer,
1503	.mmap			= avs_component_mmap,
1504	.pcm_construct		= avs_component_construct,
1505	/*
1506	 * hda platform component's probe() is dependent on
1507	 * codec->pcm_list_head, it needs to be initialized after codec
1508	 * component. remove_order is here for completeness sake
1509	 */
1510	.probe_order		= SND_SOC_COMP_ORDER_LATE,
1511	.remove_order		= SND_SOC_COMP_ORDER_EARLY,
1512	.module_get_upon_open	= 1,
1513	.topology_name_prefix	= "intel/avs",
1514};
1515
1516int avs_hda_platform_register(struct avs_dev *adev, const char *name)
1517{
1518	return avs_soc_component_register(adev->dev, name,
1519					  &avs_hda_component_driver, NULL, 0);
1520}
1521