xref: /openbmc/linux/sound/soc/intel/skylake/skl-pcm.c (revision ab10ac26)
18e8e69d6SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2a40e693cSJeeja KP /*
3a40e693cSJeeja KP  *  skl-pcm.c -ASoC HDA Platform driver file implementing PCM functionality
4a40e693cSJeeja KP  *
5a40e693cSJeeja KP  *  Copyright (C) 2014-2015 Intel Corp
6a40e693cSJeeja KP  *  Author:  Jeeja KP <jeeja.kp@intel.com>
7a40e693cSJeeja KP  *
8a40e693cSJeeja KP  *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9a40e693cSJeeja KP  *
10a40e693cSJeeja KP  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11a40e693cSJeeja KP  */
12a40e693cSJeeja KP 
13a40e693cSJeeja KP #include <linux/pci.h>
14a40e693cSJeeja KP #include <linux/pm_runtime.h>
15fdd85a05SHardik T Shah #include <linux/delay.h>
1676e3a424SAmadeusz Sławiński #include <sound/hdaudio.h>
17a40e693cSJeeja KP #include <sound/pcm_params.h>
18a40e693cSJeeja KP #include <sound/soc.h>
19a40e693cSJeeja KP #include "skl.h"
20b663a8c5SJeeja KP #include "skl-topology.h"
21721c3e36SDharageswari.R #include "skl-sst-dsp.h"
22721c3e36SDharageswari.R #include "skl-sst-ipc.h"
23a40e693cSJeeja KP 
24a40e693cSJeeja KP #define HDA_MONO 1
25a40e693cSJeeja KP #define HDA_STEREO 2
268f35bf3fSJeeja KP #define HDA_QUAD 4
273d178713SRakesh Ughreja #define HDA_MAX 8
28a40e693cSJeeja KP 
298df397ffSBhumika Goyal static const struct snd_pcm_hardware azx_pcm_hw = {
30a40e693cSJeeja KP 	.info =			(SNDRV_PCM_INFO_MMAP |
31a40e693cSJeeja KP 				 SNDRV_PCM_INFO_INTERLEAVED |
32a40e693cSJeeja KP 				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
33a40e693cSJeeja KP 				 SNDRV_PCM_INFO_MMAP_VALID |
34a40e693cSJeeja KP 				 SNDRV_PCM_INFO_PAUSE |
353637976bSJeeja KP 				 SNDRV_PCM_INFO_RESUME |
36a40e693cSJeeja KP 				 SNDRV_PCM_INFO_SYNC_START |
37a40e693cSJeeja KP 				 SNDRV_PCM_INFO_HAS_WALL_CLOCK | /* legacy */
38a40e693cSJeeja KP 				 SNDRV_PCM_INFO_HAS_LINK_ATIME |
39a40e693cSJeeja KP 				 SNDRV_PCM_INFO_NO_PERIOD_WAKEUP),
4006b23d93SJeeja KP 	.formats =		SNDRV_PCM_FMTBIT_S16_LE |
4106b23d93SJeeja KP 				SNDRV_PCM_FMTBIT_S32_LE |
4206b23d93SJeeja KP 				SNDRV_PCM_FMTBIT_S24_LE,
4306b23d93SJeeja KP 	.rates =		SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000 |
4406b23d93SJeeja KP 				SNDRV_PCM_RATE_8000,
4506b23d93SJeeja KP 	.rate_min =		8000,
46a40e693cSJeeja KP 	.rate_max =		48000,
478f35bf3fSJeeja KP 	.channels_min =		1,
487e12dc87SSubhransu S. Prusty 	.channels_max =		8,
49a40e693cSJeeja KP 	.buffer_bytes_max =	AZX_MAX_BUF_SIZE,
50a40e693cSJeeja KP 	.period_bytes_min =	128,
51a40e693cSJeeja KP 	.period_bytes_max =	AZX_MAX_BUF_SIZE / 2,
52a40e693cSJeeja KP 	.periods_min =		2,
53a40e693cSJeeja KP 	.periods_max =		AZX_MAX_FRAG,
54a40e693cSJeeja KP 	.fifo_size =		0,
55a40e693cSJeeja KP };
56a40e693cSJeeja KP 
57a40e693cSJeeja KP static inline
get_hdac_ext_stream(struct snd_pcm_substream * substream)58a40e693cSJeeja KP struct hdac_ext_stream *get_hdac_ext_stream(struct snd_pcm_substream *substream)
59a40e693cSJeeja KP {
60a40e693cSJeeja KP 	return substream->runtime->private_data;
61a40e693cSJeeja KP }
62a40e693cSJeeja KP 
get_bus_ctx(struct snd_pcm_substream * substream)6376f56faeSRakesh Ughreja static struct hdac_bus *get_bus_ctx(struct snd_pcm_substream *substream)
64a40e693cSJeeja KP {
65a40e693cSJeeja KP 	struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
66a40e693cSJeeja KP 	struct hdac_stream *hstream = hdac_stream(stream);
67a40e693cSJeeja KP 	struct hdac_bus *bus = hstream->bus;
6876f56faeSRakesh Ughreja 	return bus;
69a40e693cSJeeja KP }
70a40e693cSJeeja KP 
skl_substream_alloc_pages(struct hdac_bus * bus,struct snd_pcm_substream * substream,size_t size)7176f56faeSRakesh Ughreja static int skl_substream_alloc_pages(struct hdac_bus *bus,
72a40e693cSJeeja KP 				 struct snd_pcm_substream *substream,
73a40e693cSJeeja KP 				 size_t size)
74a40e693cSJeeja KP {
75a40e693cSJeeja KP 	struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
76a40e693cSJeeja KP 
77a40e693cSJeeja KP 	hdac_stream(stream)->bufsize = 0;
78a40e693cSJeeja KP 	hdac_stream(stream)->period_bytes = 0;
79a40e693cSJeeja KP 	hdac_stream(stream)->format_val = 0;
80a40e693cSJeeja KP 
8151240953STakashi Iwai 	return 0;
82a40e693cSJeeja KP }
83a40e693cSJeeja KP 
skl_set_pcm_constrains(struct hdac_bus * bus,struct snd_pcm_runtime * runtime)8476f56faeSRakesh Ughreja static void skl_set_pcm_constrains(struct hdac_bus *bus,
85a40e693cSJeeja KP 				 struct snd_pcm_runtime *runtime)
86a40e693cSJeeja KP {
87a40e693cSJeeja KP 	snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
88a40e693cSJeeja KP 
89a40e693cSJeeja KP 	/* avoid wrap-around with wall-clock */
90a40e693cSJeeja KP 	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_TIME,
91a40e693cSJeeja KP 				     20, 178000000);
92a40e693cSJeeja KP }
93a40e693cSJeeja KP 
skl_get_host_stream_type(struct hdac_bus * bus)9476f56faeSRakesh Ughreja static enum hdac_ext_stream_type skl_get_host_stream_type(struct hdac_bus *bus)
9505057001SJeeja KP {
9676f56faeSRakesh Ughreja 	if (bus->ppcap)
9705057001SJeeja KP 		return HDAC_EXT_STREAM_TYPE_HOST;
9805057001SJeeja KP 	else
9905057001SJeeja KP 		return HDAC_EXT_STREAM_TYPE_COUPLED;
10005057001SJeeja KP }
10105057001SJeeja KP 
1024557c305SJeeja KP /*
1034557c305SJeeja KP  * check if the stream opened is marked as ignore_suspend by machine, if so
1044557c305SJeeja KP  * then enable suspend_active refcount
1054557c305SJeeja KP  *
1064557c305SJeeja KP  * The count supend_active does not need lock as it is used in open/close
1074557c305SJeeja KP  * and suspend context
1084557c305SJeeja KP  */
skl_set_suspend_active(struct snd_pcm_substream * substream,struct snd_soc_dai * dai,bool enable)1094557c305SJeeja KP static void skl_set_suspend_active(struct snd_pcm_substream *substream,
1104557c305SJeeja KP 					 struct snd_soc_dai *dai, bool enable)
1114557c305SJeeja KP {
11276f56faeSRakesh Ughreja 	struct hdac_bus *bus = dev_get_drvdata(dai->dev);
1134557c305SJeeja KP 	struct snd_soc_dapm_widget *w;
114bcc2a2dcSCezary Rojewski 	struct skl_dev *skl = bus_to_skl(bus);
1154557c305SJeeja KP 
1160c01f6caSKuninori Morimoto 	w = snd_soc_dai_get_widget(dai, substream->stream);
1174557c305SJeeja KP 
1184557c305SJeeja KP 	if (w->ignore_suspend && enable)
1194557c305SJeeja KP 		skl->supend_active++;
1204557c305SJeeja KP 	else if (w->ignore_suspend && !enable)
1214557c305SJeeja KP 		skl->supend_active--;
1224557c305SJeeja KP }
1234557c305SJeeja KP 
skl_pcm_host_dma_prepare(struct device * dev,struct skl_pipe_params * params)124ad036bdeSJeeja KP int skl_pcm_host_dma_prepare(struct device *dev, struct skl_pipe_params *params)
125ad036bdeSJeeja KP {
12676f56faeSRakesh Ughreja 	struct hdac_bus *bus = dev_get_drvdata(dev);
127bcc2a2dcSCezary Rojewski 	struct skl_dev *skl = bus_to_skl(bus);
128ad036bdeSJeeja KP 	unsigned int format_val;
129ad036bdeSJeeja KP 	struct hdac_stream *hstream;
130ad036bdeSJeeja KP 	struct hdac_ext_stream *stream;
131ad036bdeSJeeja KP 	int err;
132ad036bdeSJeeja KP 
133ad036bdeSJeeja KP 	hstream = snd_hdac_get_stream(bus, params->stream,
134ad036bdeSJeeja KP 					params->host_dma_id + 1);
135ad036bdeSJeeja KP 	if (!hstream)
136ad036bdeSJeeja KP 		return -EINVAL;
137ad036bdeSJeeja KP 
138ad036bdeSJeeja KP 	stream = stream_to_hdac_ext_stream(hstream);
13976f56faeSRakesh Ughreja 	snd_hdac_ext_stream_decouple(bus, stream, true);
140ad036bdeSJeeja KP 
141ad036bdeSJeeja KP 	format_val = snd_hdac_calc_stream_format(params->s_freq,
1427f975a38SJeeja KP 			params->ch, params->format, params->host_bps, 0);
143ad036bdeSJeeja KP 
144ad036bdeSJeeja KP 	dev_dbg(dev, "format_val=%d, rate=%d, ch=%d, format=%d\n",
145ad036bdeSJeeja KP 		format_val, params->s_freq, params->ch, params->format);
146ad036bdeSJeeja KP 
147ad036bdeSJeeja KP 	snd_hdac_stream_reset(hdac_stream(stream));
148ad036bdeSJeeja KP 	err = snd_hdac_stream_set_params(hdac_stream(stream), format_val);
149ad036bdeSJeeja KP 	if (err < 0)
150ad036bdeSJeeja KP 		return err;
151ad036bdeSJeeja KP 
152d5fcaabaSPaweł Harłoziński 	/*
153d5fcaabaSPaweł Harłoziński 	 * The recommended SDxFMT programming sequence for BXT
154d5fcaabaSPaweł Harłoziński 	 * platforms is to couple the stream before writing the format
155d5fcaabaSPaweł Harłoziński 	 */
15676e3a424SAmadeusz Sławiński 	if (HDA_CONTROLLER_IS_APL(skl->pci)) {
157d5fcaabaSPaweł Harłoziński 		snd_hdac_ext_stream_decouple(bus, stream, false);
158ad036bdeSJeeja KP 		err = snd_hdac_stream_setup(hdac_stream(stream));
159d5fcaabaSPaweł Harłoziński 		snd_hdac_ext_stream_decouple(bus, stream, true);
160d5fcaabaSPaweł Harłoziński 	} else {
161d5fcaabaSPaweł Harłoziński 		err = snd_hdac_stream_setup(hdac_stream(stream));
162d5fcaabaSPaweł Harłoziński 	}
163d5fcaabaSPaweł Harłoziński 
164ad036bdeSJeeja KP 	if (err < 0)
165ad036bdeSJeeja KP 		return err;
166ad036bdeSJeeja KP 
167ad036bdeSJeeja KP 	hdac_stream(stream)->prepared = 1;
168ad036bdeSJeeja KP 
169ad036bdeSJeeja KP 	return 0;
170ad036bdeSJeeja KP }
171ad036bdeSJeeja KP 
skl_pcm_link_dma_prepare(struct device * dev,struct skl_pipe_params * params)172ad036bdeSJeeja KP int skl_pcm_link_dma_prepare(struct device *dev, struct skl_pipe_params *params)
173ad036bdeSJeeja KP {
17476f56faeSRakesh Ughreja 	struct hdac_bus *bus = dev_get_drvdata(dev);
175ad036bdeSJeeja KP 	unsigned int format_val;
176ad036bdeSJeeja KP 	struct hdac_stream *hstream;
177ad036bdeSJeeja KP 	struct hdac_ext_stream *stream;
178ad036bdeSJeeja KP 	struct hdac_ext_link *link;
179c899df3eSRander Wang 	unsigned char stream_tag;
180ad036bdeSJeeja KP 
181ad036bdeSJeeja KP 	hstream = snd_hdac_get_stream(bus, params->stream,
182ad036bdeSJeeja KP 					params->link_dma_id + 1);
183ad036bdeSJeeja KP 	if (!hstream)
184ad036bdeSJeeja KP 		return -EINVAL;
185ad036bdeSJeeja KP 
186ad036bdeSJeeja KP 	stream = stream_to_hdac_ext_stream(hstream);
18776f56faeSRakesh Ughreja 	snd_hdac_ext_stream_decouple(bus, stream, true);
1887f975a38SJeeja KP 	format_val = snd_hdac_calc_stream_format(params->s_freq, params->ch,
1897f975a38SJeeja KP 					params->format, params->link_bps, 0);
190ad036bdeSJeeja KP 
191ad036bdeSJeeja KP 	dev_dbg(dev, "format_val=%d, rate=%d, ch=%d, format=%d\n",
192ad036bdeSJeeja KP 		format_val, params->s_freq, params->ch, params->format);
193ad036bdeSJeeja KP 
19400b6cd95SPierre-Louis Bossart 	snd_hdac_ext_stream_reset(stream);
195ad036bdeSJeeja KP 
19600b6cd95SPierre-Louis Bossart 	snd_hdac_ext_stream_setup(stream, format_val);
197ad036bdeSJeeja KP 
198c899df3eSRander Wang 	stream_tag = hstream->stream_tag;
199c899df3eSRander Wang 	if (stream->hstream.direction == SNDRV_PCM_STREAM_PLAYBACK) {
20076f56faeSRakesh Ughreja 		list_for_each_entry(link, &bus->hlink_list, list) {
201ad036bdeSJeeja KP 			if (link->index == params->link_index)
2027fa403f2SPierre-Louis Bossart 				snd_hdac_ext_bus_link_set_stream_id(link,
203c899df3eSRander Wang 								    stream_tag);
204c899df3eSRander Wang 		}
205ad036bdeSJeeja KP 	}
206ad036bdeSJeeja KP 
207ad036bdeSJeeja KP 	stream->link_prepared = 1;
208ad036bdeSJeeja KP 
209ad036bdeSJeeja KP 	return 0;
210ad036bdeSJeeja KP }
211ad036bdeSJeeja KP 
skl_pcm_open(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)212a40e693cSJeeja KP static int skl_pcm_open(struct snd_pcm_substream *substream,
213a40e693cSJeeja KP 		struct snd_soc_dai *dai)
214a40e693cSJeeja KP {
21576f56faeSRakesh Ughreja 	struct hdac_bus *bus = dev_get_drvdata(dai->dev);
216a40e693cSJeeja KP 	struct hdac_ext_stream *stream;
217a40e693cSJeeja KP 	struct snd_pcm_runtime *runtime = substream->runtime;
218a40e693cSJeeja KP 	struct skl_dma_params *dma_params;
219bcc2a2dcSCezary Rojewski 	struct skl_dev *skl = get_skl_ctx(dai->dev);
220a83e3b4cSVinod Koul 	struct skl_module_cfg *mconfig;
221a40e693cSJeeja KP 
222a40e693cSJeeja KP 	dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
223a40e693cSJeeja KP 
22476f56faeSRakesh Ughreja 	stream = snd_hdac_ext_stream_assign(bus, substream,
22576f56faeSRakesh Ughreja 					skl_get_host_stream_type(bus));
226a40e693cSJeeja KP 	if (stream == NULL)
227a40e693cSJeeja KP 		return -EBUSY;
228a40e693cSJeeja KP 
22976f56faeSRakesh Ughreja 	skl_set_pcm_constrains(bus, runtime);
230a40e693cSJeeja KP 
231a40e693cSJeeja KP 	/*
232a40e693cSJeeja KP 	 * disable WALLCLOCK timestamps for capture streams
233a40e693cSJeeja KP 	 * until we figure out how to handle digital inputs
234a40e693cSJeeja KP 	 */
235a40e693cSJeeja KP 	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
236a40e693cSJeeja KP 		runtime->hw.info &= ~SNDRV_PCM_INFO_HAS_WALL_CLOCK; /* legacy */
237a40e693cSJeeja KP 		runtime->hw.info &= ~SNDRV_PCM_INFO_HAS_LINK_ATIME;
238a40e693cSJeeja KP 	}
239a40e693cSJeeja KP 
240a40e693cSJeeja KP 	runtime->private_data = stream;
241a40e693cSJeeja KP 
242a40e693cSJeeja KP 	dma_params = kzalloc(sizeof(*dma_params), GFP_KERNEL);
243a40e693cSJeeja KP 	if (!dma_params)
244a40e693cSJeeja KP 		return -ENOMEM;
245a40e693cSJeeja KP 
246a40e693cSJeeja KP 	dma_params->stream_tag = hdac_stream(stream)->stream_tag;
247a40e693cSJeeja KP 	snd_soc_dai_set_dma_data(dai, substream, dma_params);
248a40e693cSJeeja KP 
249a40e693cSJeeja KP 	dev_dbg(dai->dev, "stream tag set in dma params=%d\n",
250a40e693cSJeeja KP 				 dma_params->stream_tag);
2514557c305SJeeja KP 	skl_set_suspend_active(substream, dai, true);
252a40e693cSJeeja KP 	snd_pcm_set_sync(substream);
253a40e693cSJeeja KP 
254a83e3b4cSVinod Koul 	mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream);
25507c7fd07SKamil Duljas 	if (!mconfig) {
25607c7fd07SKamil Duljas 		kfree(dma_params);
25791ce5497SG Kranthi 		return -EINVAL;
25807c7fd07SKamil Duljas 	}
25991ce5497SG Kranthi 
260a83e3b4cSVinod Koul 	skl_tplg_d0i3_get(skl, mconfig->d0i3_caps);
261a83e3b4cSVinod Koul 
262a40e693cSJeeja KP 	return 0;
263a40e693cSJeeja KP }
264a40e693cSJeeja KP 
skl_pcm_prepare(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)265a40e693cSJeeja KP static int skl_pcm_prepare(struct snd_pcm_substream *substream,
266a40e693cSJeeja KP 		struct snd_soc_dai *dai)
267a40e693cSJeeja KP {
268bcc2a2dcSCezary Rojewski 	struct skl_dev *skl = get_skl_ctx(dai->dev);
2692004432fSJeeja KP 	struct skl_module_cfg *mconfig;
27074e65192SPardha Saradhi K 	int ret;
271a40e693cSJeeja KP 
272a40e693cSJeeja KP 	dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
273a40e693cSJeeja KP 
2742004432fSJeeja KP 	mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream);
2752004432fSJeeja KP 
27674e65192SPardha Saradhi K 	/*
27774e65192SPardha Saradhi K 	 * In case of XRUN recovery or in the case when the application
27874e65192SPardha Saradhi K 	 * calls prepare another time, reset the FW pipe to clean state
27974e65192SPardha Saradhi K 	 */
28074e65192SPardha Saradhi K 	if (mconfig &&
2812bd2dc26STakashi Iwai 		(substream->runtime->state == SNDRV_PCM_STATE_XRUN ||
28274e65192SPardha Saradhi K 		 mconfig->pipe->state == SKL_PIPE_CREATED ||
28374e65192SPardha Saradhi K 		 mconfig->pipe->state == SKL_PIPE_PAUSED)) {
28474e65192SPardha Saradhi K 
285bcc2a2dcSCezary Rojewski 		ret = skl_reset_pipe(skl, mconfig->pipe);
28674e65192SPardha Saradhi K 
28774e65192SPardha Saradhi K 		if (ret < 0)
28874e65192SPardha Saradhi K 			return ret;
28974e65192SPardha Saradhi K 
29074e65192SPardha Saradhi K 		ret = skl_pcm_host_dma_prepare(dai->dev,
29174e65192SPardha Saradhi K 					mconfig->pipe->p_params);
29274e65192SPardha Saradhi K 		if (ret < 0)
29374e65192SPardha Saradhi K 			return ret;
29474e65192SPardha Saradhi K 	}
2952004432fSJeeja KP 
296bb704a73SJeeja KP 	return 0;
297a40e693cSJeeja KP }
298a40e693cSJeeja KP 
skl_pcm_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)299a40e693cSJeeja KP static int skl_pcm_hw_params(struct snd_pcm_substream *substream,
300a40e693cSJeeja KP 				struct snd_pcm_hw_params *params,
301a40e693cSJeeja KP 				struct snd_soc_dai *dai)
302a40e693cSJeeja KP {
30376f56faeSRakesh Ughreja 	struct hdac_bus *bus = dev_get_drvdata(dai->dev);
30405057001SJeeja KP 	struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
305a40e693cSJeeja KP 	struct snd_pcm_runtime *runtime = substream->runtime;
306b663a8c5SJeeja KP 	struct skl_pipe_params p_params = {0};
307b663a8c5SJeeja KP 	struct skl_module_cfg *m_cfg;
30805057001SJeeja KP 	int ret, dma_id;
309a40e693cSJeeja KP 
310a40e693cSJeeja KP 	dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
31176f56faeSRakesh Ughreja 	ret = skl_substream_alloc_pages(bus, substream,
312a40e693cSJeeja KP 					  params_buffer_bytes(params));
313a40e693cSJeeja KP 	if (ret < 0)
314a40e693cSJeeja KP 		return ret;
315a40e693cSJeeja KP 
316a40e693cSJeeja KP 	dev_dbg(dai->dev, "format_val, rate=%d, ch=%d, format=%d\n",
317a40e693cSJeeja KP 			runtime->rate, runtime->channels, runtime->format);
318a40e693cSJeeja KP 
31905057001SJeeja KP 	dma_id = hdac_stream(stream)->stream_tag - 1;
32005057001SJeeja KP 	dev_dbg(dai->dev, "dma_id=%d\n", dma_id);
32105057001SJeeja KP 
322b663a8c5SJeeja KP 	p_params.s_fmt = snd_pcm_format_width(params_format(params));
323322fa431SAmadeusz Sławiński 	p_params.s_cont = snd_pcm_format_physical_width(params_format(params));
324b663a8c5SJeeja KP 	p_params.ch = params_channels(params);
325b663a8c5SJeeja KP 	p_params.s_freq = params_rate(params);
326b663a8c5SJeeja KP 	p_params.host_dma_id = dma_id;
327b663a8c5SJeeja KP 	p_params.stream = substream->stream;
32812c3be0eSJeeja KP 	p_params.format = params_format(params);
3297f975a38SJeeja KP 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
3307f975a38SJeeja KP 		p_params.host_bps = dai->driver->playback.sig_bits;
3317f975a38SJeeja KP 	else
3327f975a38SJeeja KP 		p_params.host_bps = dai->driver->capture.sig_bits;
3337f975a38SJeeja KP 
334b663a8c5SJeeja KP 
335b663a8c5SJeeja KP 	m_cfg = skl_tplg_fe_get_cpr_module(dai, p_params.stream);
336b663a8c5SJeeja KP 	if (m_cfg)
337b663a8c5SJeeja KP 		skl_tplg_update_pipe_params(dai->dev, m_cfg, &p_params);
338b663a8c5SJeeja KP 
339a40e693cSJeeja KP 	return 0;
340a40e693cSJeeja KP }
341a40e693cSJeeja KP 
skl_pcm_close(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)342a40e693cSJeeja KP static void skl_pcm_close(struct snd_pcm_substream *substream,
343a40e693cSJeeja KP 		struct snd_soc_dai *dai)
344a40e693cSJeeja KP {
345a40e693cSJeeja KP 	struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
34676f56faeSRakesh Ughreja 	struct hdac_bus *bus = dev_get_drvdata(dai->dev);
347a40e693cSJeeja KP 	struct skl_dma_params *dma_params = NULL;
348bcc2a2dcSCezary Rojewski 	struct skl_dev *skl = bus_to_skl(bus);
349a83e3b4cSVinod Koul 	struct skl_module_cfg *mconfig;
350a40e693cSJeeja KP 
351a40e693cSJeeja KP 	dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
35205057001SJeeja KP 
35376f56faeSRakesh Ughreja 	snd_hdac_ext_stream_release(stream, skl_get_host_stream_type(bus));
354a40e693cSJeeja KP 
355a40e693cSJeeja KP 	dma_params = snd_soc_dai_get_dma_data(dai, substream);
356a40e693cSJeeja KP 	/*
357a40e693cSJeeja KP 	 * now we should set this to NULL as we are freeing by the
358a40e693cSJeeja KP 	 * dma_params
359a40e693cSJeeja KP 	 */
360a40e693cSJeeja KP 	snd_soc_dai_set_dma_data(dai, substream, NULL);
3614557c305SJeeja KP 	skl_set_suspend_active(substream, dai, false);
362a40e693cSJeeja KP 
363721c3e36SDharageswari.R 	/*
364721c3e36SDharageswari.R 	 * check if close is for "Reference Pin" and set back the
365721c3e36SDharageswari.R 	 * CGCTL.MISCBDCGE if disabled by driver
366721c3e36SDharageswari.R 	 */
367721c3e36SDharageswari.R 	if (!strncmp(dai->name, "Reference Pin", 13) &&
368bcc2a2dcSCezary Rojewski 			skl->miscbdcg_disabled) {
369bcc2a2dcSCezary Rojewski 		skl->enable_miscbdcge(dai->dev, true);
370bcc2a2dcSCezary Rojewski 		skl->miscbdcg_disabled = false;
371721c3e36SDharageswari.R 	}
372721c3e36SDharageswari.R 
373a83e3b4cSVinod Koul 	mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream);
3740265ddd7SPankaj Bharadiya 	if (mconfig)
375a83e3b4cSVinod Koul 		skl_tplg_d0i3_put(skl, mconfig->d0i3_caps);
376a83e3b4cSVinod Koul 
377a40e693cSJeeja KP 	kfree(dma_params);
378a40e693cSJeeja KP }
379a40e693cSJeeja KP 
skl_pcm_hw_free(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)380a40e693cSJeeja KP static int skl_pcm_hw_free(struct snd_pcm_substream *substream,
381a40e693cSJeeja KP 		struct snd_soc_dai *dai)
382a40e693cSJeeja KP {
383a40e693cSJeeja KP 	struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
384bcc2a2dcSCezary Rojewski 	struct skl_dev *skl = get_skl_ctx(dai->dev);
385179c2e86SDivya Prakash 	struct skl_module_cfg *mconfig;
386179c2e86SDivya Prakash 	int ret;
387a40e693cSJeeja KP 
388a40e693cSJeeja KP 	dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
389a40e693cSJeeja KP 
390179c2e86SDivya Prakash 	mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream);
391179c2e86SDivya Prakash 
392179c2e86SDivya Prakash 	if (mconfig) {
393bcc2a2dcSCezary Rojewski 		ret = skl_reset_pipe(skl, mconfig->pipe);
394179c2e86SDivya Prakash 		if (ret < 0)
395179c2e86SDivya Prakash 			dev_err(dai->dev, "%s:Reset failed ret =%d",
396179c2e86SDivya Prakash 						__func__, ret);
397179c2e86SDivya Prakash 	}
398179c2e86SDivya Prakash 
399a40e693cSJeeja KP 	snd_hdac_stream_cleanup(hdac_stream(stream));
400a40e693cSJeeja KP 	hdac_stream(stream)->prepared = 0;
401a40e693cSJeeja KP 
40251240953STakashi Iwai 	return 0;
403a40e693cSJeeja KP }
404a40e693cSJeeja KP 
skl_be_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)405b663a8c5SJeeja KP static int skl_be_hw_params(struct snd_pcm_substream *substream,
406b663a8c5SJeeja KP 				struct snd_pcm_hw_params *params,
407b663a8c5SJeeja KP 				struct snd_soc_dai *dai)
408b663a8c5SJeeja KP {
409b663a8c5SJeeja KP 	struct skl_pipe_params p_params = {0};
410b663a8c5SJeeja KP 
411b663a8c5SJeeja KP 	p_params.s_fmt = snd_pcm_format_width(params_format(params));
412322fa431SAmadeusz Sławiński 	p_params.s_cont = snd_pcm_format_physical_width(params_format(params));
413b663a8c5SJeeja KP 	p_params.ch = params_channels(params);
414b663a8c5SJeeja KP 	p_params.s_freq = params_rate(params);
415b663a8c5SJeeja KP 	p_params.stream = substream->stream;
416b663a8c5SJeeja KP 
4174bd073f9SJeeja KP 	return skl_tplg_be_update_params(dai, &p_params);
418b663a8c5SJeeja KP }
419b663a8c5SJeeja KP 
skl_decoupled_trigger(struct snd_pcm_substream * substream,int cmd)420d1730c3dSJeeja KP static int skl_decoupled_trigger(struct snd_pcm_substream *substream,
421d1730c3dSJeeja KP 		int cmd)
422d1730c3dSJeeja KP {
42376f56faeSRakesh Ughreja 	struct hdac_bus *bus = get_bus_ctx(substream);
424d1730c3dSJeeja KP 	struct hdac_ext_stream *stream;
425d1730c3dSJeeja KP 	int start;
426d1730c3dSJeeja KP 	unsigned long cookie;
427d1730c3dSJeeja KP 	struct hdac_stream *hstr;
428d1730c3dSJeeja KP 
429d1730c3dSJeeja KP 	stream = get_hdac_ext_stream(substream);
430d1730c3dSJeeja KP 	hstr = hdac_stream(stream);
431d1730c3dSJeeja KP 
432d1730c3dSJeeja KP 	if (!hstr->prepared)
433d1730c3dSJeeja KP 		return -EPIPE;
434d1730c3dSJeeja KP 
435d1730c3dSJeeja KP 	switch (cmd) {
436d1730c3dSJeeja KP 	case SNDRV_PCM_TRIGGER_START:
437d1730c3dSJeeja KP 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
438d1730c3dSJeeja KP 	case SNDRV_PCM_TRIGGER_RESUME:
439d1730c3dSJeeja KP 		start = 1;
440d1730c3dSJeeja KP 		break;
441d1730c3dSJeeja KP 
442d1730c3dSJeeja KP 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
443d1730c3dSJeeja KP 	case SNDRV_PCM_TRIGGER_SUSPEND:
444d1730c3dSJeeja KP 	case SNDRV_PCM_TRIGGER_STOP:
445d1730c3dSJeeja KP 		start = 0;
446d1730c3dSJeeja KP 		break;
447d1730c3dSJeeja KP 
448d1730c3dSJeeja KP 	default:
449d1730c3dSJeeja KP 		return -EINVAL;
450d1730c3dSJeeja KP 	}
451d1730c3dSJeeja KP 
452d1730c3dSJeeja KP 	spin_lock_irqsave(&bus->reg_lock, cookie);
453d1730c3dSJeeja KP 
454d1730c3dSJeeja KP 	if (start) {
4554fe20d62SZhang Yiqun 		snd_hdac_stream_start(hdac_stream(stream));
456d1730c3dSJeeja KP 		snd_hdac_stream_timecounter_init(hstr, 0);
457d1730c3dSJeeja KP 	} else {
458d1730c3dSJeeja KP 		snd_hdac_stream_stop(hdac_stream(stream));
459d1730c3dSJeeja KP 	}
460d1730c3dSJeeja KP 
461d1730c3dSJeeja KP 	spin_unlock_irqrestore(&bus->reg_lock, cookie);
462d1730c3dSJeeja KP 
463d1730c3dSJeeja KP 	return 0;
464d1730c3dSJeeja KP }
465d1730c3dSJeeja KP 
skl_pcm_trigger(struct snd_pcm_substream * substream,int cmd,struct snd_soc_dai * dai)466b663a8c5SJeeja KP static int skl_pcm_trigger(struct snd_pcm_substream *substream, int cmd,
467b663a8c5SJeeja KP 		struct snd_soc_dai *dai)
468b663a8c5SJeeja KP {
469bcc2a2dcSCezary Rojewski 	struct skl_dev *skl = get_skl_ctx(dai->dev);
470b663a8c5SJeeja KP 	struct skl_module_cfg *mconfig;
47176f56faeSRakesh Ughreja 	struct hdac_bus *bus = get_bus_ctx(substream);
4727e3a17d3SJeeja KP 	struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
47362582341SPierre-Louis Bossart 	struct hdac_stream *hstream = hdac_stream(stream);
4749a655db0SJeeja KP 	struct snd_soc_dapm_widget *w;
475d1730c3dSJeeja KP 	int ret;
476b663a8c5SJeeja KP 
477b663a8c5SJeeja KP 	mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream);
478b663a8c5SJeeja KP 	if (!mconfig)
479b663a8c5SJeeja KP 		return -EIO;
480b663a8c5SJeeja KP 
4810c01f6caSKuninori Morimoto 	w = snd_soc_dai_get_widget(dai, substream->stream);
4829a655db0SJeeja KP 
483b663a8c5SJeeja KP 	switch (cmd) {
4847e3a17d3SJeeja KP 	case SNDRV_PCM_TRIGGER_RESUME:
4859a655db0SJeeja KP 		if (!w->ignore_suspend) {
486748a1d5aSJeeja KP 			/*
4879a655db0SJeeja KP 			 * enable DMA Resume enable bit for the stream, set the
4889a655db0SJeeja KP 			 * dpib & lpib position to resume before starting the
4899a655db0SJeeja KP 			 * DMA
490748a1d5aSJeeja KP 			 */
49162582341SPierre-Louis Bossart 			snd_hdac_stream_drsm_enable(bus, true, hstream->index);
49262582341SPierre-Louis Bossart 			snd_hdac_stream_set_dpibr(bus, hstream, hstream->lpib);
49362582341SPierre-Louis Bossart 			snd_hdac_stream_set_lpib(hstream, hstream->lpib);
4949a655db0SJeeja KP 		}
495df561f66SGustavo A. R. Silva 		fallthrough;
496748a1d5aSJeeja KP 
497d1730c3dSJeeja KP 	case SNDRV_PCM_TRIGGER_START:
498b663a8c5SJeeja KP 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
499d1730c3dSJeeja KP 		/*
500d1730c3dSJeeja KP 		 * Start HOST DMA and Start FE Pipe.This is to make sure that
501d1730c3dSJeeja KP 		 * there are no underrun/overrun in the case when the FE
502d1730c3dSJeeja KP 		 * pipeline is started but there is a delay in starting the
503d1730c3dSJeeja KP 		 * DMA channel on the host.
504d1730c3dSJeeja KP 		 */
505d1730c3dSJeeja KP 		ret = skl_decoupled_trigger(substream, cmd);
506d1730c3dSJeeja KP 		if (ret < 0)
507d1730c3dSJeeja KP 			return ret;
508bcc2a2dcSCezary Rojewski 		return skl_run_pipe(skl, mconfig->pipe);
509b663a8c5SJeeja KP 
510b663a8c5SJeeja KP 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
511b663a8c5SJeeja KP 	case SNDRV_PCM_TRIGGER_SUSPEND:
512d1730c3dSJeeja KP 	case SNDRV_PCM_TRIGGER_STOP:
513d1730c3dSJeeja KP 		/*
514d1730c3dSJeeja KP 		 * Stop FE Pipe first and stop DMA. This is to make sure that
515d1730c3dSJeeja KP 		 * there are no underrun/overrun in the case if there is a delay
516d1730c3dSJeeja KP 		 * between the two operations.
517d1730c3dSJeeja KP 		 */
518bcc2a2dcSCezary Rojewski 		ret = skl_stop_pipe(skl, mconfig->pipe);
519d1730c3dSJeeja KP 		if (ret < 0)
520d1730c3dSJeeja KP 			return ret;
521d1730c3dSJeeja KP 
522d1730c3dSJeeja KP 		ret = skl_decoupled_trigger(substream, cmd);
5239a655db0SJeeja KP 		if ((cmd == SNDRV_PCM_TRIGGER_SUSPEND) && !w->ignore_suspend) {
524748a1d5aSJeeja KP 			/* save the dpib and lpib positions */
52562582341SPierre-Louis Bossart 			hstream->dpib = readl(bus->remap_addr +
526748a1d5aSJeeja KP 					AZX_REG_VS_SDXDPIB_XBASE +
527748a1d5aSJeeja KP 					(AZX_REG_VS_SDXDPIB_XINTERVAL *
52862582341SPierre-Louis Bossart 					hstream->index));
529748a1d5aSJeeja KP 
53062582341SPierre-Louis Bossart 			hstream->lpib = snd_hdac_stream_get_pos_lpib(hstream);
53162582341SPierre-Louis Bossart 
53276f56faeSRakesh Ughreja 			snd_hdac_ext_stream_decouple(bus, stream, false);
533748a1d5aSJeeja KP 		}
534d1730c3dSJeeja KP 		break;
535b663a8c5SJeeja KP 
536b663a8c5SJeeja KP 	default:
537d1730c3dSJeeja KP 		return -EINVAL;
538b663a8c5SJeeja KP 	}
539d1730c3dSJeeja KP 
540d1730c3dSJeeja KP 	return 0;
541b663a8c5SJeeja KP }
542b663a8c5SJeeja KP 
54376f56faeSRakesh Ughreja 
skl_link_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)54405057001SJeeja KP static int skl_link_hw_params(struct snd_pcm_substream *substream,
54505057001SJeeja KP 				struct snd_pcm_hw_params *params,
54605057001SJeeja KP 				struct snd_soc_dai *dai)
54705057001SJeeja KP {
54876f56faeSRakesh Ughreja 	struct hdac_bus *bus = dev_get_drvdata(dai->dev);
54905057001SJeeja KP 	struct hdac_ext_stream *link_dev;
5502ab9a409SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
5510d1571c1SKuninori Morimoto 	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
552b663a8c5SJeeja KP 	struct skl_pipe_params p_params = {0};
55312c3be0eSJeeja KP 	struct hdac_ext_link *link;
5541011509dSJeeja KP 	int stream_tag;
55505057001SJeeja KP 
55676f56faeSRakesh Ughreja 	link_dev = snd_hdac_ext_stream_assign(bus, substream,
55705057001SJeeja KP 					HDAC_EXT_STREAM_TYPE_LINK);
55805057001SJeeja KP 	if (!link_dev)
55905057001SJeeja KP 		return -EBUSY;
56005057001SJeeja KP 
56105057001SJeeja KP 	snd_soc_dai_set_dma_data(dai, substream, (void *)link_dev);
56205057001SJeeja KP 
563b0cd60f3SPierre-Louis Bossart 	link = snd_hdac_ext_bus_get_hlink_by_name(bus, codec_dai->component->name);
56412c3be0eSJeeja KP 	if (!link)
56512c3be0eSJeeja KP 		return -EINVAL;
56612c3be0eSJeeja KP 
5671011509dSJeeja KP 	stream_tag = hdac_stream(link_dev)->stream_tag;
5681011509dSJeeja KP 
56963611041SPierre-Louis Bossart 	/* set the hdac_stream in the codec dai */
57063611041SPierre-Louis Bossart 	snd_soc_dai_set_stream(codec_dai, hdac_stream(link_dev), substream->stream);
571b663a8c5SJeeja KP 
572b663a8c5SJeeja KP 	p_params.s_fmt = snd_pcm_format_width(params_format(params));
573322fa431SAmadeusz Sławiński 	p_params.s_cont = snd_pcm_format_physical_width(params_format(params));
574b663a8c5SJeeja KP 	p_params.ch = params_channels(params);
575b663a8c5SJeeja KP 	p_params.s_freq = params_rate(params);
576b663a8c5SJeeja KP 	p_params.stream = substream->stream;
5771011509dSJeeja KP 	p_params.link_dma_id = stream_tag - 1;
57812c3be0eSJeeja KP 	p_params.link_index = link->index;
57912c3be0eSJeeja KP 	p_params.format = params_format(params);
580b663a8c5SJeeja KP 
5817f975a38SJeeja KP 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
5827f975a38SJeeja KP 		p_params.link_bps = codec_dai->driver->playback.sig_bits;
5837f975a38SJeeja KP 	else
5847f975a38SJeeja KP 		p_params.link_bps = codec_dai->driver->capture.sig_bits;
5857f975a38SJeeja KP 
5864bd073f9SJeeja KP 	return skl_tplg_be_update_params(dai, &p_params);
58705057001SJeeja KP }
58805057001SJeeja KP 
skl_link_pcm_prepare(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)58905057001SJeeja KP static int skl_link_pcm_prepare(struct snd_pcm_substream *substream,
59005057001SJeeja KP 		struct snd_soc_dai *dai)
59105057001SJeeja KP {
592bcc2a2dcSCezary Rojewski 	struct skl_dev *skl = get_skl_ctx(dai->dev);
5932004432fSJeeja KP 	struct skl_module_cfg *mconfig = NULL;
59405057001SJeeja KP 
5952004432fSJeeja KP 	/* In case of XRUN recovery, reset the FW pipe to clean state */
5962004432fSJeeja KP 	mconfig = skl_tplg_be_get_cpr_module(dai, substream->stream);
5977cbfdf87SJeeja KP 	if (mconfig && !mconfig->pipe->passthru &&
5982bd2dc26STakashi Iwai 		(substream->runtime->state == SNDRV_PCM_STATE_XRUN))
599bcc2a2dcSCezary Rojewski 		skl_reset_pipe(skl, mconfig->pipe);
6002004432fSJeeja KP 
60105057001SJeeja KP 	return 0;
60205057001SJeeja KP }
60305057001SJeeja KP 
skl_link_pcm_trigger(struct snd_pcm_substream * substream,int cmd,struct snd_soc_dai * dai)60405057001SJeeja KP static int skl_link_pcm_trigger(struct snd_pcm_substream *substream,
60505057001SJeeja KP 	int cmd, struct snd_soc_dai *dai)
60605057001SJeeja KP {
60705057001SJeeja KP 	struct hdac_ext_stream *link_dev =
60805057001SJeeja KP 				snd_soc_dai_get_dma_data(dai, substream);
60976f56faeSRakesh Ughreja 	struct hdac_bus *bus = get_bus_ctx(substream);
610920982c9SJeeja KP 	struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
61105057001SJeeja KP 
61205057001SJeeja KP 	dev_dbg(dai->dev, "In %s cmd=%d\n", __func__, cmd);
61305057001SJeeja KP 	switch (cmd) {
614920982c9SJeeja KP 	case SNDRV_PCM_TRIGGER_RESUME:
61505057001SJeeja KP 	case SNDRV_PCM_TRIGGER_START:
61605057001SJeeja KP 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
61700b6cd95SPierre-Louis Bossart 		snd_hdac_ext_stream_start(link_dev);
61805057001SJeeja KP 		break;
61905057001SJeeja KP 
62005057001SJeeja KP 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
62105057001SJeeja KP 	case SNDRV_PCM_TRIGGER_SUSPEND:
62205057001SJeeja KP 	case SNDRV_PCM_TRIGGER_STOP:
62300b6cd95SPierre-Louis Bossart 		snd_hdac_ext_stream_clear(link_dev);
624920982c9SJeeja KP 		if (cmd == SNDRV_PCM_TRIGGER_SUSPEND)
62576f56faeSRakesh Ughreja 			snd_hdac_ext_stream_decouple(bus, stream, false);
62605057001SJeeja KP 		break;
62705057001SJeeja KP 
62805057001SJeeja KP 	default:
62905057001SJeeja KP 		return -EINVAL;
63005057001SJeeja KP 	}
63105057001SJeeja KP 	return 0;
63205057001SJeeja KP }
63305057001SJeeja KP 
skl_link_hw_free(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)63405057001SJeeja KP static int skl_link_hw_free(struct snd_pcm_substream *substream,
63505057001SJeeja KP 		struct snd_soc_dai *dai)
63605057001SJeeja KP {
63776f56faeSRakesh Ughreja 	struct hdac_bus *bus = dev_get_drvdata(dai->dev);
6382ab9a409SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
63905057001SJeeja KP 	struct hdac_ext_stream *link_dev =
64005057001SJeeja KP 				snd_soc_dai_get_dma_data(dai, substream);
64105057001SJeeja KP 	struct hdac_ext_link *link;
642c899df3eSRander Wang 	unsigned char stream_tag;
64305057001SJeeja KP 
64405057001SJeeja KP 	dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
64505057001SJeeja KP 
64605057001SJeeja KP 	link_dev->link_prepared = 0;
64705057001SJeeja KP 
648b0cd60f3SPierre-Louis Bossart 	link = snd_hdac_ext_bus_get_hlink_by_name(bus, asoc_rtd_to_codec(rtd, 0)->component->name);
64905057001SJeeja KP 	if (!link)
65005057001SJeeja KP 		return -EINVAL;
65105057001SJeeja KP 
652c899df3eSRander Wang 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
653c899df3eSRander Wang 		stream_tag = hdac_stream(link_dev)->stream_tag;
6547fa403f2SPierre-Louis Bossart 		snd_hdac_ext_bus_link_clear_stream_id(link, stream_tag);
655c899df3eSRander Wang 	}
656c899df3eSRander Wang 
65705057001SJeeja KP 	snd_hdac_ext_stream_release(link_dev, HDAC_EXT_STREAM_TYPE_LINK);
65805057001SJeeja KP 	return 0;
65905057001SJeeja KP }
66005057001SJeeja KP 
66182e2b1e0SGustavo A. R. Silva static const struct snd_soc_dai_ops skl_pcm_dai_ops = {
662a40e693cSJeeja KP 	.startup = skl_pcm_open,
663a40e693cSJeeja KP 	.shutdown = skl_pcm_close,
664a40e693cSJeeja KP 	.prepare = skl_pcm_prepare,
665a40e693cSJeeja KP 	.hw_params = skl_pcm_hw_params,
666a40e693cSJeeja KP 	.hw_free = skl_pcm_hw_free,
667b663a8c5SJeeja KP 	.trigger = skl_pcm_trigger,
668a40e693cSJeeja KP };
669a40e693cSJeeja KP 
67082e2b1e0SGustavo A. R. Silva static const struct snd_soc_dai_ops skl_dmic_dai_ops = {
671b663a8c5SJeeja KP 	.hw_params = skl_be_hw_params,
672b663a8c5SJeeja KP };
673b663a8c5SJeeja KP 
67482e2b1e0SGustavo A. R. Silva static const struct snd_soc_dai_ops skl_be_ssp_dai_ops = {
675b663a8c5SJeeja KP 	.hw_params = skl_be_hw_params,
67605057001SJeeja KP };
67705057001SJeeja KP 
67882e2b1e0SGustavo A. R. Silva static const struct snd_soc_dai_ops skl_link_dai_ops = {
67905057001SJeeja KP 	.prepare = skl_link_pcm_prepare,
68005057001SJeeja KP 	.hw_params = skl_link_hw_params,
68105057001SJeeja KP 	.hw_free = skl_link_hw_free,
68205057001SJeeja KP 	.trigger = skl_link_pcm_trigger,
68305057001SJeeja KP };
68405057001SJeeja KP 
685c3ae22e3SGuneshwor Singh static struct snd_soc_dai_driver skl_fe_dai[] = {
686a40e693cSJeeja KP {
687a40e693cSJeeja KP 	.name = "System Pin",
688a40e693cSJeeja KP 	.ops = &skl_pcm_dai_ops,
689a40e693cSJeeja KP 	.playback = {
690a40e693cSJeeja KP 		.stream_name = "System Playback",
691a40e693cSJeeja KP 		.channels_min = HDA_MONO,
692a40e693cSJeeja KP 		.channels_max = HDA_STEREO,
693a40e693cSJeeja KP 		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_8000,
694dde53bccSSamaga Krishna 		.formats = SNDRV_PCM_FMTBIT_S16_LE |
695dde53bccSSamaga Krishna 			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE,
6967f975a38SJeeja KP 		.sig_bits = 32,
697a40e693cSJeeja KP 	},
698a40e693cSJeeja KP 	.capture = {
699a40e693cSJeeja KP 		.stream_name = "System Capture",
700a40e693cSJeeja KP 		.channels_min = HDA_MONO,
701a40e693cSJeeja KP 		.channels_max = HDA_STEREO,
702a40e693cSJeeja KP 		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000,
703a40e693cSJeeja KP 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
7047f975a38SJeeja KP 		.sig_bits = 32,
705a40e693cSJeeja KP 	},
706a40e693cSJeeja KP },
707a40e693cSJeeja KP {
708da3cbb40SNaveen Manohar 	.name = "System Pin2",
709da3cbb40SNaveen Manohar 	.ops = &skl_pcm_dai_ops,
710da3cbb40SNaveen Manohar 	.playback = {
711da3cbb40SNaveen Manohar 		.stream_name = "Headset Playback",
712da3cbb40SNaveen Manohar 		.channels_min = HDA_MONO,
713da3cbb40SNaveen Manohar 		.channels_max = HDA_STEREO,
714da3cbb40SNaveen Manohar 		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000 |
715da3cbb40SNaveen Manohar 			SNDRV_PCM_RATE_8000,
716da3cbb40SNaveen Manohar 		.formats = SNDRV_PCM_FMTBIT_S16_LE |
717da3cbb40SNaveen Manohar 			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE,
718da3cbb40SNaveen Manohar 	},
719da3cbb40SNaveen Manohar },
720da3cbb40SNaveen Manohar {
721da3cbb40SNaveen Manohar 	.name = "Echoref Pin",
722da3cbb40SNaveen Manohar 	.ops = &skl_pcm_dai_ops,
723da3cbb40SNaveen Manohar 	.capture = {
724da3cbb40SNaveen Manohar 		.stream_name = "Echoreference Capture",
725da3cbb40SNaveen Manohar 		.channels_min = HDA_STEREO,
726da3cbb40SNaveen Manohar 		.channels_max = HDA_STEREO,
727da3cbb40SNaveen Manohar 		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000 |
728da3cbb40SNaveen Manohar 			SNDRV_PCM_RATE_8000,
729da3cbb40SNaveen Manohar 		.formats = SNDRV_PCM_FMTBIT_S16_LE |
730da3cbb40SNaveen Manohar 			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE,
731da3cbb40SNaveen Manohar 	},
732da3cbb40SNaveen Manohar },
733da3cbb40SNaveen Manohar {
73405057001SJeeja KP 	.name = "Reference Pin",
73505057001SJeeja KP 	.ops = &skl_pcm_dai_ops,
73605057001SJeeja KP 	.capture = {
73705057001SJeeja KP 		.stream_name = "Reference Capture",
73805057001SJeeja KP 		.channels_min = HDA_MONO,
7398f35bf3fSJeeja KP 		.channels_max = HDA_QUAD,
74005057001SJeeja KP 		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000,
74105057001SJeeja KP 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
7427f975a38SJeeja KP 		.sig_bits = 32,
74305057001SJeeja KP 	},
74405057001SJeeja KP },
74505057001SJeeja KP {
746a40e693cSJeeja KP 	.name = "Deepbuffer Pin",
747a40e693cSJeeja KP 	.ops = &skl_pcm_dai_ops,
748a40e693cSJeeja KP 	.playback = {
749a40e693cSJeeja KP 		.stream_name = "Deepbuffer Playback",
750a40e693cSJeeja KP 		.channels_min = HDA_STEREO,
751a40e693cSJeeja KP 		.channels_max = HDA_STEREO,
752a40e693cSJeeja KP 		.rates = SNDRV_PCM_RATE_48000,
753a40e693cSJeeja KP 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
7547f975a38SJeeja KP 		.sig_bits = 32,
755a40e693cSJeeja KP 	},
756a40e693cSJeeja KP },
757a40e693cSJeeja KP {
758a40e693cSJeeja KP 	.name = "LowLatency Pin",
759a40e693cSJeeja KP 	.ops = &skl_pcm_dai_ops,
760a40e693cSJeeja KP 	.playback = {
761a40e693cSJeeja KP 		.stream_name = "Low Latency Playback",
762a40e693cSJeeja KP 		.channels_min = HDA_STEREO,
763a40e693cSJeeja KP 		.channels_max = HDA_STEREO,
764a40e693cSJeeja KP 		.rates = SNDRV_PCM_RATE_48000,
765a40e693cSJeeja KP 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
7667f975a38SJeeja KP 		.sig_bits = 32,
767a40e693cSJeeja KP 	},
768a40e693cSJeeja KP },
7698f35bf3fSJeeja KP {
7708f35bf3fSJeeja KP 	.name = "DMIC Pin",
7718f35bf3fSJeeja KP 	.ops = &skl_pcm_dai_ops,
7728f35bf3fSJeeja KP 	.capture = {
7738f35bf3fSJeeja KP 		.stream_name = "DMIC Capture",
7748f35bf3fSJeeja KP 		.channels_min = HDA_MONO,
7758f35bf3fSJeeja KP 		.channels_max = HDA_QUAD,
7768f35bf3fSJeeja KP 		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000,
7778f35bf3fSJeeja KP 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
7787f975a38SJeeja KP 		.sig_bits = 32,
7798f35bf3fSJeeja KP 	},
7808f35bf3fSJeeja KP },
7818cca87c0SSubhransu S. Prusty {
7828cca87c0SSubhransu S. Prusty 	.name = "HDMI1 Pin",
7838cca87c0SSubhransu S. Prusty 	.ops = &skl_pcm_dai_ops,
7848cca87c0SSubhransu S. Prusty 	.playback = {
7858cca87c0SSubhransu S. Prusty 		.stream_name = "HDMI1 Playback",
7868cca87c0SSubhransu S. Prusty 		.channels_min = HDA_STEREO,
7877e12dc87SSubhransu S. Prusty 		.channels_max = 8,
7888cca87c0SSubhransu S. Prusty 		.rates = SNDRV_PCM_RATE_32000 |	SNDRV_PCM_RATE_44100 |
7898cca87c0SSubhransu S. Prusty 			SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |
7908cca87c0SSubhransu S. Prusty 			SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |
7918cca87c0SSubhransu S. Prusty 			SNDRV_PCM_RATE_192000,
7928cca87c0SSubhransu S. Prusty 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
7938cca87c0SSubhransu S. Prusty 			SNDRV_PCM_FMTBIT_S32_LE,
7947f975a38SJeeja KP 		.sig_bits = 32,
7958cca87c0SSubhransu S. Prusty 	},
7968cca87c0SSubhransu S. Prusty },
7978cca87c0SSubhransu S. Prusty {
7988cca87c0SSubhransu S. Prusty 	.name = "HDMI2 Pin",
7998cca87c0SSubhransu S. Prusty 	.ops = &skl_pcm_dai_ops,
8008cca87c0SSubhransu S. Prusty 	.playback = {
8018cca87c0SSubhransu S. Prusty 		.stream_name = "HDMI2 Playback",
8028cca87c0SSubhransu S. Prusty 		.channels_min = HDA_STEREO,
8037e12dc87SSubhransu S. Prusty 		.channels_max = 8,
8048cca87c0SSubhransu S. Prusty 		.rates = SNDRV_PCM_RATE_32000 |	SNDRV_PCM_RATE_44100 |
8058cca87c0SSubhransu S. Prusty 			SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |
8068cca87c0SSubhransu S. Prusty 			SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |
8078cca87c0SSubhransu S. Prusty 			SNDRV_PCM_RATE_192000,
8088cca87c0SSubhransu S. Prusty 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
8098cca87c0SSubhransu S. Prusty 			SNDRV_PCM_FMTBIT_S32_LE,
8107f975a38SJeeja KP 		.sig_bits = 32,
8118cca87c0SSubhransu S. Prusty 	},
8128cca87c0SSubhransu S. Prusty },
8138cca87c0SSubhransu S. Prusty {
8148cca87c0SSubhransu S. Prusty 	.name = "HDMI3 Pin",
8158cca87c0SSubhransu S. Prusty 	.ops = &skl_pcm_dai_ops,
8168cca87c0SSubhransu S. Prusty 	.playback = {
8178cca87c0SSubhransu S. Prusty 		.stream_name = "HDMI3 Playback",
8188cca87c0SSubhransu S. Prusty 		.channels_min = HDA_STEREO,
8197e12dc87SSubhransu S. Prusty 		.channels_max = 8,
8208cca87c0SSubhransu S. Prusty 		.rates = SNDRV_PCM_RATE_32000 |	SNDRV_PCM_RATE_44100 |
8218cca87c0SSubhransu S. Prusty 			SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |
8228cca87c0SSubhransu S. Prusty 			SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |
8238cca87c0SSubhransu S. Prusty 			SNDRV_PCM_RATE_192000,
8248cca87c0SSubhransu S. Prusty 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
8258cca87c0SSubhransu S. Prusty 			SNDRV_PCM_FMTBIT_S32_LE,
8267f975a38SJeeja KP 		.sig_bits = 32,
8278cca87c0SSubhransu S. Prusty 	},
8288cca87c0SSubhransu S. Prusty },
829c3ae22e3SGuneshwor Singh };
8308f35bf3fSJeeja KP 
83105057001SJeeja KP /* BE CPU  Dais */
832c3ae22e3SGuneshwor Singh static struct snd_soc_dai_driver skl_platform_dai[] = {
83305057001SJeeja KP {
834b663a8c5SJeeja KP 	.name = "SSP0 Pin",
835b663a8c5SJeeja KP 	.ops = &skl_be_ssp_dai_ops,
836b663a8c5SJeeja KP 	.playback = {
837b663a8c5SJeeja KP 		.stream_name = "ssp0 Tx",
838b663a8c5SJeeja KP 		.channels_min = HDA_STEREO,
839b663a8c5SJeeja KP 		.channels_max = HDA_STEREO,
840b663a8c5SJeeja KP 		.rates = SNDRV_PCM_RATE_48000,
841b663a8c5SJeeja KP 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
842b663a8c5SJeeja KP 	},
843b663a8c5SJeeja KP 	.capture = {
844b663a8c5SJeeja KP 		.stream_name = "ssp0 Rx",
845b663a8c5SJeeja KP 		.channels_min = HDA_STEREO,
846b663a8c5SJeeja KP 		.channels_max = HDA_STEREO,
847b663a8c5SJeeja KP 		.rates = SNDRV_PCM_RATE_48000,
848b663a8c5SJeeja KP 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
849b663a8c5SJeeja KP 	},
850b663a8c5SJeeja KP },
851b663a8c5SJeeja KP {
852c80fd4daSJeeja KP 	.name = "SSP1 Pin",
853c80fd4daSJeeja KP 	.ops = &skl_be_ssp_dai_ops,
854c80fd4daSJeeja KP 	.playback = {
855c80fd4daSJeeja KP 		.stream_name = "ssp1 Tx",
856c80fd4daSJeeja KP 		.channels_min = HDA_STEREO,
857c80fd4daSJeeja KP 		.channels_max = HDA_STEREO,
858c80fd4daSJeeja KP 		.rates = SNDRV_PCM_RATE_48000,
859c80fd4daSJeeja KP 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
860c80fd4daSJeeja KP 	},
861c80fd4daSJeeja KP 	.capture = {
862c80fd4daSJeeja KP 		.stream_name = "ssp1 Rx",
863c80fd4daSJeeja KP 		.channels_min = HDA_STEREO,
864c80fd4daSJeeja KP 		.channels_max = HDA_STEREO,
865c80fd4daSJeeja KP 		.rates = SNDRV_PCM_RATE_48000,
866c80fd4daSJeeja KP 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
867c80fd4daSJeeja KP 	},
868c80fd4daSJeeja KP },
869c80fd4daSJeeja KP {
870fcc494afSPardha Saradhi K 	.name = "SSP2 Pin",
871fcc494afSPardha Saradhi K 	.ops = &skl_be_ssp_dai_ops,
872fcc494afSPardha Saradhi K 	.playback = {
873fcc494afSPardha Saradhi K 		.stream_name = "ssp2 Tx",
874fcc494afSPardha Saradhi K 		.channels_min = HDA_STEREO,
875fcc494afSPardha Saradhi K 		.channels_max = HDA_STEREO,
876fcc494afSPardha Saradhi K 		.rates = SNDRV_PCM_RATE_48000,
877fcc494afSPardha Saradhi K 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
878fcc494afSPardha Saradhi K 	},
879fcc494afSPardha Saradhi K 	.capture = {
880fcc494afSPardha Saradhi K 		.stream_name = "ssp2 Rx",
881fcc494afSPardha Saradhi K 		.channels_min = HDA_STEREO,
882fcc494afSPardha Saradhi K 		.channels_max = HDA_STEREO,
883fcc494afSPardha Saradhi K 		.rates = SNDRV_PCM_RATE_48000,
884fcc494afSPardha Saradhi K 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
885fcc494afSPardha Saradhi K 	},
886fcc494afSPardha Saradhi K },
887fcc494afSPardha Saradhi K {
888fcc494afSPardha Saradhi K 	.name = "SSP3 Pin",
889fcc494afSPardha Saradhi K 	.ops = &skl_be_ssp_dai_ops,
890fcc494afSPardha Saradhi K 	.playback = {
891fcc494afSPardha Saradhi K 		.stream_name = "ssp3 Tx",
892fcc494afSPardha Saradhi K 		.channels_min = HDA_STEREO,
893fcc494afSPardha Saradhi K 		.channels_max = HDA_STEREO,
894fcc494afSPardha Saradhi K 		.rates = SNDRV_PCM_RATE_48000,
895fcc494afSPardha Saradhi K 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
896fcc494afSPardha Saradhi K 	},
897fcc494afSPardha Saradhi K 	.capture = {
898fcc494afSPardha Saradhi K 		.stream_name = "ssp3 Rx",
899fcc494afSPardha Saradhi K 		.channels_min = HDA_STEREO,
900fcc494afSPardha Saradhi K 		.channels_max = HDA_STEREO,
901fcc494afSPardha Saradhi K 		.rates = SNDRV_PCM_RATE_48000,
902fcc494afSPardha Saradhi K 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
903fcc494afSPardha Saradhi K 	},
904fcc494afSPardha Saradhi K },
905fcc494afSPardha Saradhi K {
906fcc494afSPardha Saradhi K 	.name = "SSP4 Pin",
907fcc494afSPardha Saradhi K 	.ops = &skl_be_ssp_dai_ops,
908fcc494afSPardha Saradhi K 	.playback = {
909fcc494afSPardha Saradhi K 		.stream_name = "ssp4 Tx",
910fcc494afSPardha Saradhi K 		.channels_min = HDA_STEREO,
911fcc494afSPardha Saradhi K 		.channels_max = HDA_STEREO,
912fcc494afSPardha Saradhi K 		.rates = SNDRV_PCM_RATE_48000,
913fcc494afSPardha Saradhi K 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
914fcc494afSPardha Saradhi K 	},
915fcc494afSPardha Saradhi K 	.capture = {
916fcc494afSPardha Saradhi K 		.stream_name = "ssp4 Rx",
917fcc494afSPardha Saradhi K 		.channels_min = HDA_STEREO,
918fcc494afSPardha Saradhi K 		.channels_max = HDA_STEREO,
919fcc494afSPardha Saradhi K 		.rates = SNDRV_PCM_RATE_48000,
920fcc494afSPardha Saradhi K 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
921fcc494afSPardha Saradhi K 	},
922fcc494afSPardha Saradhi K },
923fcc494afSPardha Saradhi K {
924fcc494afSPardha Saradhi K 	.name = "SSP5 Pin",
925fcc494afSPardha Saradhi K 	.ops = &skl_be_ssp_dai_ops,
926fcc494afSPardha Saradhi K 	.playback = {
927fcc494afSPardha Saradhi K 		.stream_name = "ssp5 Tx",
928fcc494afSPardha Saradhi K 		.channels_min = HDA_STEREO,
929fcc494afSPardha Saradhi K 		.channels_max = HDA_STEREO,
930fcc494afSPardha Saradhi K 		.rates = SNDRV_PCM_RATE_48000,
931fcc494afSPardha Saradhi K 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
932fcc494afSPardha Saradhi K 	},
933fcc494afSPardha Saradhi K 	.capture = {
934fcc494afSPardha Saradhi K 		.stream_name = "ssp5 Rx",
935fcc494afSPardha Saradhi K 		.channels_min = HDA_STEREO,
936fcc494afSPardha Saradhi K 		.channels_max = HDA_STEREO,
937fcc494afSPardha Saradhi K 		.rates = SNDRV_PCM_RATE_48000,
938fcc494afSPardha Saradhi K 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
939fcc494afSPardha Saradhi K 	},
940fcc494afSPardha Saradhi K },
941fcc494afSPardha Saradhi K {
9428cca87c0SSubhransu S. Prusty 	.name = "iDisp1 Pin",
94305057001SJeeja KP 	.ops = &skl_link_dai_ops,
94405057001SJeeja KP 	.playback = {
9458cca87c0SSubhransu S. Prusty 		.stream_name = "iDisp1 Tx",
94605057001SJeeja KP 		.channels_min = HDA_STEREO,
9477e12dc87SSubhransu S. Prusty 		.channels_max = 8,
94805057001SJeeja KP 		.rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|SNDRV_PCM_RATE_48000,
9498cca87c0SSubhransu S. Prusty 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE |
9508cca87c0SSubhransu S. Prusty 			SNDRV_PCM_FMTBIT_S24_LE,
9518cca87c0SSubhransu S. Prusty 	},
9528cca87c0SSubhransu S. Prusty },
9538cca87c0SSubhransu S. Prusty {
9548cca87c0SSubhransu S. Prusty 	.name = "iDisp2 Pin",
9558cca87c0SSubhransu S. Prusty 	.ops = &skl_link_dai_ops,
9568cca87c0SSubhransu S. Prusty 	.playback = {
9578cca87c0SSubhransu S. Prusty 		.stream_name = "iDisp2 Tx",
9588cca87c0SSubhransu S. Prusty 		.channels_min = HDA_STEREO,
9597e12dc87SSubhransu S. Prusty 		.channels_max = 8,
9608cca87c0SSubhransu S. Prusty 		.rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|
9618cca87c0SSubhransu S. Prusty 			SNDRV_PCM_RATE_48000,
9628cca87c0SSubhransu S. Prusty 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE |
9638cca87c0SSubhransu S. Prusty 			SNDRV_PCM_FMTBIT_S24_LE,
9648cca87c0SSubhransu S. Prusty 	},
9658cca87c0SSubhransu S. Prusty },
9668cca87c0SSubhransu S. Prusty {
9678cca87c0SSubhransu S. Prusty 	.name = "iDisp3 Pin",
9688cca87c0SSubhransu S. Prusty 	.ops = &skl_link_dai_ops,
9698cca87c0SSubhransu S. Prusty 	.playback = {
9708cca87c0SSubhransu S. Prusty 		.stream_name = "iDisp3 Tx",
9718cca87c0SSubhransu S. Prusty 		.channels_min = HDA_STEREO,
9727e12dc87SSubhransu S. Prusty 		.channels_max = 8,
9738cca87c0SSubhransu S. Prusty 		.rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|
9748cca87c0SSubhransu S. Prusty 			SNDRV_PCM_RATE_48000,
9758cca87c0SSubhransu S. Prusty 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE |
9768cca87c0SSubhransu S. Prusty 			SNDRV_PCM_FMTBIT_S24_LE,
97705057001SJeeja KP 	},
97805057001SJeeja KP },
97905057001SJeeja KP {
98005057001SJeeja KP 	.name = "DMIC01 Pin",
98105057001SJeeja KP 	.ops = &skl_dmic_dai_ops,
98205057001SJeeja KP 	.capture = {
98305057001SJeeja KP 		.stream_name = "DMIC01 Rx",
9848f35bf3fSJeeja KP 		.channels_min = HDA_MONO,
9858f35bf3fSJeeja KP 		.channels_max = HDA_QUAD,
98605057001SJeeja KP 		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000,
98705057001SJeeja KP 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
98805057001SJeeja KP 	},
98905057001SJeeja KP },
99005057001SJeeja KP {
99166b48606SPawse, GuruprasadX 	.name = "DMIC16k Pin",
99266b48606SPawse, GuruprasadX 	.ops = &skl_dmic_dai_ops,
99366b48606SPawse, GuruprasadX 	.capture = {
99466b48606SPawse, GuruprasadX 		.stream_name = "DMIC16k Rx",
99566b48606SPawse, GuruprasadX 		.channels_min = HDA_MONO,
99666b48606SPawse, GuruprasadX 		.channels_max = HDA_QUAD,
99766b48606SPawse, GuruprasadX 		.rates = SNDRV_PCM_RATE_16000,
99866b48606SPawse, GuruprasadX 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
99966b48606SPawse, GuruprasadX 	},
100066b48606SPawse, GuruprasadX },
100166b48606SPawse, GuruprasadX {
10023d178713SRakesh Ughreja 	.name = "Analog CPU DAI",
100305057001SJeeja KP 	.ops = &skl_link_dai_ops,
100405057001SJeeja KP 	.playback = {
10053d178713SRakesh Ughreja 		.stream_name = "Analog CPU Playback",
10063d178713SRakesh Ughreja 		.channels_min = HDA_MONO,
10073d178713SRakesh Ughreja 		.channels_max = HDA_MAX,
10083d178713SRakesh Ughreja 		.rates = SNDRV_PCM_RATE_8000_192000,
10093d178713SRakesh Ughreja 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
10103d178713SRakesh Ughreja 			SNDRV_PCM_FMTBIT_S32_LE,
101105057001SJeeja KP 	},
101205057001SJeeja KP 	.capture = {
10133d178713SRakesh Ughreja 		.stream_name = "Analog CPU Capture",
10143d178713SRakesh Ughreja 		.channels_min = HDA_MONO,
10153d178713SRakesh Ughreja 		.channels_max = HDA_MAX,
10163d178713SRakesh Ughreja 		.rates = SNDRV_PCM_RATE_8000_192000,
10173d178713SRakesh Ughreja 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
10183d178713SRakesh Ughreja 			SNDRV_PCM_FMTBIT_S32_LE,
10193d178713SRakesh Ughreja 	},
10203d178713SRakesh Ughreja },
10213d178713SRakesh Ughreja {
10223d178713SRakesh Ughreja 	.name = "Alt Analog CPU DAI",
10233d178713SRakesh Ughreja 	.ops = &skl_link_dai_ops,
10243d178713SRakesh Ughreja 	.playback = {
10253d178713SRakesh Ughreja 		.stream_name = "Alt Analog CPU Playback",
10263d178713SRakesh Ughreja 		.channels_min = HDA_MONO,
10273d178713SRakesh Ughreja 		.channels_max = HDA_MAX,
10283d178713SRakesh Ughreja 		.rates = SNDRV_PCM_RATE_8000_192000,
10293d178713SRakesh Ughreja 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
10303d178713SRakesh Ughreja 			SNDRV_PCM_FMTBIT_S32_LE,
10313d178713SRakesh Ughreja 	},
10323d178713SRakesh Ughreja 	.capture = {
10333d178713SRakesh Ughreja 		.stream_name = "Alt Analog CPU Capture",
10343d178713SRakesh Ughreja 		.channels_min = HDA_MONO,
10353d178713SRakesh Ughreja 		.channels_max = HDA_MAX,
10363d178713SRakesh Ughreja 		.rates = SNDRV_PCM_RATE_8000_192000,
10373d178713SRakesh Ughreja 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
10383d178713SRakesh Ughreja 			SNDRV_PCM_FMTBIT_S32_LE,
10393d178713SRakesh Ughreja 	},
10403d178713SRakesh Ughreja },
10413d178713SRakesh Ughreja {
10423d178713SRakesh Ughreja 	.name = "Digital CPU DAI",
10433d178713SRakesh Ughreja 	.ops = &skl_link_dai_ops,
10443d178713SRakesh Ughreja 	.playback = {
10453d178713SRakesh Ughreja 		.stream_name = "Digital CPU Playback",
10463d178713SRakesh Ughreja 		.channels_min = HDA_MONO,
10473d178713SRakesh Ughreja 		.channels_max = HDA_MAX,
10483d178713SRakesh Ughreja 		.rates = SNDRV_PCM_RATE_8000_192000,
10493d178713SRakesh Ughreja 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
10503d178713SRakesh Ughreja 			SNDRV_PCM_FMTBIT_S32_LE,
10513d178713SRakesh Ughreja 	},
10523d178713SRakesh Ughreja 	.capture = {
10533d178713SRakesh Ughreja 		.stream_name = "Digital CPU Capture",
10543d178713SRakesh Ughreja 		.channels_min = HDA_MONO,
10553d178713SRakesh Ughreja 		.channels_max = HDA_MAX,
10563d178713SRakesh Ughreja 		.rates = SNDRV_PCM_RATE_8000_192000,
10573d178713SRakesh Ughreja 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
10583d178713SRakesh Ughreja 			SNDRV_PCM_FMTBIT_S32_LE,
105905057001SJeeja KP 	},
106005057001SJeeja KP },
1061a40e693cSJeeja KP };
1062a40e693cSJeeja KP 
skl_dai_load(struct snd_soc_component * cmp,int index,struct snd_soc_dai_driver * dai_drv,struct snd_soc_tplg_pcm * pcm,struct snd_soc_dai * dai)1063c60b613aSLiam Girdwood int skl_dai_load(struct snd_soc_component *cmp, int index,
1064c60b613aSLiam Girdwood 			struct snd_soc_dai_driver *dai_drv,
1065c60b613aSLiam Girdwood 			struct snd_soc_tplg_pcm *pcm, struct snd_soc_dai *dai)
1066606e21fdSGuneshwor Singh {
1067c60b613aSLiam Girdwood 	dai_drv->ops = &skl_pcm_dai_ops;
1068606e21fdSGuneshwor Singh 
1069606e21fdSGuneshwor Singh 	return 0;
1070606e21fdSGuneshwor Singh }
1071606e21fdSGuneshwor Singh 
skl_platform_soc_open(struct snd_soc_component * component,struct snd_pcm_substream * substream)10723507bb5fSKuninori Morimoto static int skl_platform_soc_open(struct snd_soc_component *component,
10733507bb5fSKuninori Morimoto 				 struct snd_pcm_substream *substream)
1074a40e693cSJeeja KP {
10752ab9a409SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
1076a40e693cSJeeja KP 	struct snd_soc_dai_link *dai_link = rtd->dai_link;
1077a40e693cSJeeja KP 
10780d1571c1SKuninori Morimoto 	dev_dbg(asoc_rtd_to_cpu(rtd, 0)->dev, "In %s:%s\n", __func__,
10792bfa8c35SKuninori Morimoto 					dai_link->cpus->dai_name);
1080a40e693cSJeeja KP 
1081a40e693cSJeeja KP 	snd_soc_set_runtime_hwparams(substream, &azx_pcm_hw);
1082a40e693cSJeeja KP 
1083a40e693cSJeeja KP 	return 0;
1084a40e693cSJeeja KP }
1085a40e693cSJeeja KP 
skl_coupled_trigger(struct snd_pcm_substream * substream,int cmd)1086b663a8c5SJeeja KP static int skl_coupled_trigger(struct snd_pcm_substream *substream,
1087a40e693cSJeeja KP 					int cmd)
1088a40e693cSJeeja KP {
108976f56faeSRakesh Ughreja 	struct hdac_bus *bus = get_bus_ctx(substream);
1090a40e693cSJeeja KP 	struct hdac_ext_stream *stream;
1091a40e693cSJeeja KP 	struct snd_pcm_substream *s;
1092a40e693cSJeeja KP 	bool start;
1093a40e693cSJeeja KP 	int sbits = 0;
1094a40e693cSJeeja KP 	unsigned long cookie;
1095a40e693cSJeeja KP 	struct hdac_stream *hstr;
1096a40e693cSJeeja KP 
1097a40e693cSJeeja KP 	stream = get_hdac_ext_stream(substream);
1098a40e693cSJeeja KP 	hstr = hdac_stream(stream);
1099a40e693cSJeeja KP 
1100a40e693cSJeeja KP 	dev_dbg(bus->dev, "In %s cmd=%d\n", __func__, cmd);
1101a40e693cSJeeja KP 
1102a40e693cSJeeja KP 	if (!hstr->prepared)
1103a40e693cSJeeja KP 		return -EPIPE;
1104a40e693cSJeeja KP 
1105a40e693cSJeeja KP 	switch (cmd) {
1106a40e693cSJeeja KP 	case SNDRV_PCM_TRIGGER_START:
1107a40e693cSJeeja KP 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
1108a40e693cSJeeja KP 	case SNDRV_PCM_TRIGGER_RESUME:
1109a40e693cSJeeja KP 		start = true;
1110a40e693cSJeeja KP 		break;
1111a40e693cSJeeja KP 
1112a40e693cSJeeja KP 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
1113a40e693cSJeeja KP 	case SNDRV_PCM_TRIGGER_SUSPEND:
1114a40e693cSJeeja KP 	case SNDRV_PCM_TRIGGER_STOP:
1115a40e693cSJeeja KP 		start = false;
1116a40e693cSJeeja KP 		break;
1117a40e693cSJeeja KP 
1118a40e693cSJeeja KP 	default:
1119a40e693cSJeeja KP 		return -EINVAL;
1120a40e693cSJeeja KP 	}
1121a40e693cSJeeja KP 
1122a40e693cSJeeja KP 	snd_pcm_group_for_each_entry(s, substream) {
1123a40e693cSJeeja KP 		if (s->pcm->card != substream->pcm->card)
1124a40e693cSJeeja KP 			continue;
1125a40e693cSJeeja KP 		stream = get_hdac_ext_stream(s);
1126a40e693cSJeeja KP 		sbits |= 1 << hdac_stream(stream)->index;
1127a40e693cSJeeja KP 		snd_pcm_trigger_done(s, substream);
1128a40e693cSJeeja KP 	}
1129a40e693cSJeeja KP 
1130a40e693cSJeeja KP 	spin_lock_irqsave(&bus->reg_lock, cookie);
1131a40e693cSJeeja KP 
1132a40e693cSJeeja KP 	/* first, set SYNC bits of corresponding streams */
1133a40e693cSJeeja KP 	snd_hdac_stream_sync_trigger(hstr, true, sbits, AZX_REG_SSYNC);
1134a40e693cSJeeja KP 
1135a40e693cSJeeja KP 	snd_pcm_group_for_each_entry(s, substream) {
1136a40e693cSJeeja KP 		if (s->pcm->card != substream->pcm->card)
1137a40e693cSJeeja KP 			continue;
1138a40e693cSJeeja KP 		stream = get_hdac_ext_stream(s);
1139a40e693cSJeeja KP 		if (start)
11404fe20d62SZhang Yiqun 			snd_hdac_stream_start(hdac_stream(stream));
1141a40e693cSJeeja KP 		else
1142a40e693cSJeeja KP 			snd_hdac_stream_stop(hdac_stream(stream));
1143a40e693cSJeeja KP 	}
1144a40e693cSJeeja KP 	spin_unlock_irqrestore(&bus->reg_lock, cookie);
1145a40e693cSJeeja KP 
1146a40e693cSJeeja KP 	snd_hdac_stream_sync(hstr, start, sbits);
1147a40e693cSJeeja KP 
1148a40e693cSJeeja KP 	spin_lock_irqsave(&bus->reg_lock, cookie);
1149a40e693cSJeeja KP 
1150a40e693cSJeeja KP 	/* reset SYNC bits */
1151a40e693cSJeeja KP 	snd_hdac_stream_sync_trigger(hstr, false, sbits, AZX_REG_SSYNC);
1152a40e693cSJeeja KP 	if (start)
1153a40e693cSJeeja KP 		snd_hdac_stream_timecounter_init(hstr, sbits);
1154a40e693cSJeeja KP 	spin_unlock_irqrestore(&bus->reg_lock, cookie);
1155a40e693cSJeeja KP 
1156a40e693cSJeeja KP 	return 0;
1157a40e693cSJeeja KP }
1158a40e693cSJeeja KP 
skl_platform_soc_trigger(struct snd_soc_component * component,struct snd_pcm_substream * substream,int cmd)11593507bb5fSKuninori Morimoto static int skl_platform_soc_trigger(struct snd_soc_component *component,
11603507bb5fSKuninori Morimoto 				    struct snd_pcm_substream *substream,
116105057001SJeeja KP 				    int cmd)
116205057001SJeeja KP {
116376f56faeSRakesh Ughreja 	struct hdac_bus *bus = get_bus_ctx(substream);
116405057001SJeeja KP 
116576f56faeSRakesh Ughreja 	if (!bus->ppcap)
1166b663a8c5SJeeja KP 		return skl_coupled_trigger(substream, cmd);
1167d1730c3dSJeeja KP 
1168d1730c3dSJeeja KP 	return 0;
116905057001SJeeja KP }
117005057001SJeeja KP 
skl_platform_soc_pointer(struct snd_soc_component * component,struct snd_pcm_substream * substream)11713507bb5fSKuninori Morimoto static snd_pcm_uframes_t skl_platform_soc_pointer(
11723507bb5fSKuninori Morimoto 	struct snd_soc_component *component,
11733507bb5fSKuninori Morimoto 	struct snd_pcm_substream *substream)
1174a40e693cSJeeja KP {
11757b96144dSJeeja KP 	struct hdac_ext_stream *hstream = get_hdac_ext_stream(substream);
117676f56faeSRakesh Ughreja 	struct hdac_bus *bus = get_bus_ctx(substream);
1177a40e693cSJeeja KP 	unsigned int pos;
1178a40e693cSJeeja KP 
1179ca590c1cSDharageswari R 	/*
1180ca590c1cSDharageswari R 	 * Use DPIB for Playback stream as the periodic DMA Position-in-
1181ca590c1cSDharageswari R 	 * Buffer Writes may be scheduled at the same time or later than
1182ca590c1cSDharageswari R 	 * the MSI and does not guarantee to reflect the Position of the
1183ca590c1cSDharageswari R 	 * last buffer that was transferred. Whereas DPIB register in
1184ca590c1cSDharageswari R 	 * HAD space reflects the actual data that is transferred.
1185ca590c1cSDharageswari R 	 * Use the position buffer for capture, as DPIB write gets
1186ca590c1cSDharageswari R 	 * completed earlier than the actual data written to the DDR.
1187fdd85a05SHardik T Shah 	 *
1188fdd85a05SHardik T Shah 	 * For capture stream following workaround is required to fix the
1189fdd85a05SHardik T Shah 	 * incorrect position reporting.
1190fdd85a05SHardik T Shah 	 *
1191fdd85a05SHardik T Shah 	 * 1. Wait for 20us before reading the DMA position in buffer once
1192fdd85a05SHardik T Shah 	 * the interrupt is generated for stream completion as update happens
1193fdd85a05SHardik T Shah 	 * on the HDA frame boundary i.e. 20.833uSec.
1194fdd85a05SHardik T Shah 	 * 2. Read DPIB register to flush the DMA position value. This dummy
1195fdd85a05SHardik T Shah 	 * read is required to flush DMA position value.
1196fdd85a05SHardik T Shah 	 * 3. Read the DMA Position-in-Buffer. This value now will be equal to
1197fdd85a05SHardik T Shah 	 * or greater than period boundary.
1198ca590c1cSDharageswari R 	 */
1199fdd85a05SHardik T Shah 
1200fdd85a05SHardik T Shah 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
120176f56faeSRakesh Ughreja 		pos = readl(bus->remap_addr + AZX_REG_VS_SDXDPIB_XBASE +
1202ca590c1cSDharageswari R 				(AZX_REG_VS_SDXDPIB_XINTERVAL *
1203ca590c1cSDharageswari R 				hdac_stream(hstream)->index));
1204fdd85a05SHardik T Shah 	} else {
1205fdd85a05SHardik T Shah 		udelay(20);
120676f56faeSRakesh Ughreja 		readl(bus->remap_addr +
1207fdd85a05SHardik T Shah 				AZX_REG_VS_SDXDPIB_XBASE +
1208fdd85a05SHardik T Shah 				(AZX_REG_VS_SDXDPIB_XINTERVAL *
1209fdd85a05SHardik T Shah 				 hdac_stream(hstream)->index));
1210a40e693cSJeeja KP 		pos = snd_hdac_stream_get_pos_posbuf(hdac_stream(hstream));
1211fdd85a05SHardik T Shah 	}
1212a40e693cSJeeja KP 
1213a40e693cSJeeja KP 	if (pos >= hdac_stream(hstream)->bufsize)
1214a40e693cSJeeja KP 		pos = 0;
1215a40e693cSJeeja KP 
12167b96144dSJeeja KP 	return bytes_to_frames(substream->runtime, pos);
1217a40e693cSJeeja KP }
1218a40e693cSJeeja KP 
skl_adjust_codec_delay(struct snd_pcm_substream * substream,u64 nsec)1219a40e693cSJeeja KP static u64 skl_adjust_codec_delay(struct snd_pcm_substream *substream,
1220a40e693cSJeeja KP 				u64 nsec)
1221a40e693cSJeeja KP {
12222ab9a409SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
12230d1571c1SKuninori Morimoto 	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
1224a40e693cSJeeja KP 	u64 codec_frames, codec_nsecs;
1225a40e693cSJeeja KP 
1226a40e693cSJeeja KP 	if (!codec_dai->driver->ops->delay)
1227a40e693cSJeeja KP 		return nsec;
1228a40e693cSJeeja KP 
1229a40e693cSJeeja KP 	codec_frames = codec_dai->driver->ops->delay(substream, codec_dai);
1230a40e693cSJeeja KP 	codec_nsecs = div_u64(codec_frames * 1000000000LL,
1231a40e693cSJeeja KP 			      substream->runtime->rate);
1232a40e693cSJeeja KP 
1233a40e693cSJeeja KP 	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
1234a40e693cSJeeja KP 		return nsec + codec_nsecs;
1235a40e693cSJeeja KP 
1236a40e693cSJeeja KP 	return (nsec > codec_nsecs) ? nsec - codec_nsecs : 0;
1237a40e693cSJeeja KP }
1238a40e693cSJeeja KP 
skl_platform_soc_get_time_info(struct snd_soc_component * component,struct snd_pcm_substream * substream,struct timespec64 * system_ts,struct timespec64 * audio_ts,struct snd_pcm_audio_tstamp_config * audio_tstamp_config,struct snd_pcm_audio_tstamp_report * audio_tstamp_report)12393507bb5fSKuninori Morimoto static int skl_platform_soc_get_time_info(
12403507bb5fSKuninori Morimoto 			struct snd_soc_component *component,
12413507bb5fSKuninori Morimoto 			struct snd_pcm_substream *substream,
1242fcae40c9SBaolin Wang 			struct timespec64 *system_ts, struct timespec64 *audio_ts,
1243a40e693cSJeeja KP 			struct snd_pcm_audio_tstamp_config *audio_tstamp_config,
1244a40e693cSJeeja KP 			struct snd_pcm_audio_tstamp_report *audio_tstamp_report)
1245a40e693cSJeeja KP {
1246a40e693cSJeeja KP 	struct hdac_ext_stream *sstream = get_hdac_ext_stream(substream);
1247a40e693cSJeeja KP 	struct hdac_stream *hstr = hdac_stream(sstream);
1248a40e693cSJeeja KP 	u64 nsec;
1249a40e693cSJeeja KP 
1250a40e693cSJeeja KP 	if ((substream->runtime->hw.info & SNDRV_PCM_INFO_HAS_LINK_ATIME) &&
1251a40e693cSJeeja KP 		(audio_tstamp_config->type_requested == SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK)) {
1252a40e693cSJeeja KP 
1253a40e693cSJeeja KP 		snd_pcm_gettime(substream->runtime, system_ts);
1254a40e693cSJeeja KP 
1255a40e693cSJeeja KP 		nsec = timecounter_read(&hstr->tc);
1256a40e693cSJeeja KP 		if (audio_tstamp_config->report_delay)
1257a40e693cSJeeja KP 			nsec = skl_adjust_codec_delay(substream, nsec);
1258a40e693cSJeeja KP 
1259fcae40c9SBaolin Wang 		*audio_ts = ns_to_timespec64(nsec);
1260a40e693cSJeeja KP 
1261a40e693cSJeeja KP 		audio_tstamp_report->actual_type = SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK;
1262a40e693cSJeeja KP 		audio_tstamp_report->accuracy_report = 1; /* rest of struct is valid */
1263a40e693cSJeeja KP 		audio_tstamp_report->accuracy = 42; /* 24MHzWallClk == 42ns resolution */
1264a40e693cSJeeja KP 
1265a40e693cSJeeja KP 	} else {
1266a40e693cSJeeja KP 		audio_tstamp_report->actual_type = SNDRV_PCM_AUDIO_TSTAMP_TYPE_DEFAULT;
1267a40e693cSJeeja KP 	}
1268a40e693cSJeeja KP 
1269a40e693cSJeeja KP 	return 0;
1270a40e693cSJeeja KP }
1271a40e693cSJeeja KP 
1272a40e693cSJeeja KP #define MAX_PREALLOC_SIZE	(32 * 1024 * 1024)
1273a40e693cSJeeja KP 
skl_platform_soc_new(struct snd_soc_component * component,struct snd_soc_pcm_runtime * rtd)12743507bb5fSKuninori Morimoto static int skl_platform_soc_new(struct snd_soc_component *component,
12753507bb5fSKuninori Morimoto 				struct snd_soc_pcm_runtime *rtd)
1276a40e693cSJeeja KP {
12770d1571c1SKuninori Morimoto 	struct snd_soc_dai *dai = asoc_rtd_to_cpu(rtd, 0);
127876f56faeSRakesh Ughreja 	struct hdac_bus *bus = dev_get_drvdata(dai->dev);
1279a40e693cSJeeja KP 	struct snd_pcm *pcm = rtd->pcm;
1280a40e693cSJeeja KP 	unsigned int size;
1281bcc2a2dcSCezary Rojewski 	struct skl_dev *skl = bus_to_skl(bus);
1282a40e693cSJeeja KP 
1283a40e693cSJeeja KP 	if (dai->driver->playback.channels_min ||
1284a40e693cSJeeja KP 		dai->driver->capture.channels_min) {
1285a40e693cSJeeja KP 		/* buffer pre-allocation */
1286a40e693cSJeeja KP 		size = CONFIG_SND_HDA_PREALLOC_SIZE * 1024;
1287a40e693cSJeeja KP 		if (size > MAX_PREALLOC_SIZE)
1288a40e693cSJeeja KP 			size = MAX_PREALLOC_SIZE;
128951240953STakashi Iwai 		snd_pcm_set_managed_buffer_all(pcm,
1290a40e693cSJeeja KP 					       SNDRV_DMA_TYPE_DEV_SG,
12916420c24aSTakashi Iwai 					       &skl->pci->dev,
1292a40e693cSJeeja KP 					       size, MAX_PREALLOC_SIZE);
1293a40e693cSJeeja KP 	}
1294a40e693cSJeeja KP 
129562961dd5STakashi Iwai 	return 0;
1296a40e693cSJeeja KP }
1297a40e693cSJeeja KP 
skl_get_module_info(struct skl_dev * skl,struct skl_module_cfg * mconfig)1298bcc2a2dcSCezary Rojewski static int skl_get_module_info(struct skl_dev *skl,
1299bcc2a2dcSCezary Rojewski 		struct skl_module_cfg *mconfig)
1300b26199eaSJeeja KP {
130191fe0e70SJeeja KP 	struct skl_module_inst_id *pin_id;
13029e0784d0SAndy Shevchenko 	guid_t *uuid_mod, *uuid_tplg;
130391fe0e70SJeeja KP 	struct skl_module *skl_module;
1304b26199eaSJeeja KP 	struct uuid_module *module;
130591fe0e70SJeeja KP 	int i, ret = -EIO;
1306b26199eaSJeeja KP 
13079e0784d0SAndy Shevchenko 	uuid_mod = (guid_t *)mconfig->guid;
1308b26199eaSJeeja KP 
1309bcc2a2dcSCezary Rojewski 	if (list_empty(&skl->uuid_list)) {
1310bcc2a2dcSCezary Rojewski 		dev_err(skl->dev, "Module list is empty\n");
1311b26199eaSJeeja KP 		return -EIO;
1312b26199eaSJeeja KP 	}
1313b26199eaSJeeja KP 
131491fe0e70SJeeja KP 	for (i = 0; i < skl->nr_modules; i++) {
131591fe0e70SJeeja KP 		skl_module = skl->modules[i];
131691fe0e70SJeeja KP 		uuid_tplg = &skl_module->uuid;
13179e0784d0SAndy Shevchenko 		if (guid_equal(uuid_mod, uuid_tplg)) {
131891fe0e70SJeeja KP 			mconfig->module = skl_module;
131991fe0e70SJeeja KP 			ret = 0;
132091fe0e70SJeeja KP 			break;
132191fe0e70SJeeja KP 		}
132291fe0e70SJeeja KP 	}
1323c5ed9c54SGustaw Lewandowski 
132491fe0e70SJeeja KP 	if (skl->nr_modules && ret)
132591fe0e70SJeeja KP 		return ret;
132691fe0e70SJeeja KP 
1327c5ed9c54SGustaw Lewandowski 	ret = -EIO;
1328bcc2a2dcSCezary Rojewski 	list_for_each_entry(module, &skl->uuid_list, list) {
1329c5ed9c54SGustaw Lewandowski 		if (guid_equal(uuid_mod, &module->uuid)) {
1330c5ed9c54SGustaw Lewandowski 			mconfig->id.module_id = module->id;
1331c5ed9c54SGustaw Lewandowski 			mconfig->module->loadable = module->is_loadable;
1332c5ed9c54SGustaw Lewandowski 			ret = 0;
1333c5ed9c54SGustaw Lewandowski 		}
1334c5ed9c54SGustaw Lewandowski 
133591fe0e70SJeeja KP 		for (i = 0; i < MAX_IN_QUEUE; i++) {
133691fe0e70SJeeja KP 			pin_id = &mconfig->m_in_pin[i].id;
13379e0784d0SAndy Shevchenko 			if (guid_equal(&pin_id->mod_uuid, &module->uuid))
133891fe0e70SJeeja KP 				pin_id->module_id = module->id;
133991fe0e70SJeeja KP 		}
134091fe0e70SJeeja KP 
134191fe0e70SJeeja KP 		for (i = 0; i < MAX_OUT_QUEUE; i++) {
134291fe0e70SJeeja KP 			pin_id = &mconfig->m_out_pin[i].id;
13439e0784d0SAndy Shevchenko 			if (guid_equal(&pin_id->mod_uuid, &module->uuid))
134491fe0e70SJeeja KP 				pin_id->module_id = module->id;
134591fe0e70SJeeja KP 		}
134691fe0e70SJeeja KP 	}
134791fe0e70SJeeja KP 
1348c5ed9c54SGustaw Lewandowski 	return ret;
1349b26199eaSJeeja KP }
1350b26199eaSJeeja KP 
skl_populate_modules(struct skl_dev * skl)1351bcc2a2dcSCezary Rojewski static int skl_populate_modules(struct skl_dev *skl)
135264cb1d0aSVinod Koul {
135364cb1d0aSVinod Koul 	struct skl_pipeline *p;
135464cb1d0aSVinod Koul 	struct skl_pipe_module *m;
135564cb1d0aSVinod Koul 	struct snd_soc_dapm_widget *w;
135664cb1d0aSVinod Koul 	struct skl_module_cfg *mconfig;
1357b26199eaSJeeja KP 	int ret = 0;
135864cb1d0aSVinod Koul 
135964cb1d0aSVinod Koul 	list_for_each_entry(p, &skl->ppl_list, node) {
136064cb1d0aSVinod Koul 		list_for_each_entry(m, &p->pipe->w_list, node) {
136164cb1d0aSVinod Koul 			w = m->w;
136264cb1d0aSVinod Koul 			mconfig = w->priv;
136364cb1d0aSVinod Koul 
1364b26199eaSJeeja KP 			ret = skl_get_module_info(skl, mconfig);
136564cb1d0aSVinod Koul 			if (ret < 0) {
1366bcc2a2dcSCezary Rojewski 				dev_err(skl->dev,
1367b26199eaSJeeja KP 					"query module info failed\n");
1368b26199eaSJeeja KP 				return ret;
136964cb1d0aSVinod Koul 			}
1370f7a9f772SSriram Periyasamy 
1371f7a9f772SSriram Periyasamy 			skl_tplg_add_moduleid_in_bind_params(skl, w);
137264cb1d0aSVinod Koul 		}
137364cb1d0aSVinod Koul 	}
1374b26199eaSJeeja KP 
137564cb1d0aSVinod Koul 	return ret;
137664cb1d0aSVinod Koul }
137764cb1d0aSVinod Koul 
skl_platform_soc_probe(struct snd_soc_component * component)137856b03b4cSKuninori Morimoto static int skl_platform_soc_probe(struct snd_soc_component *component)
1379b663a8c5SJeeja KP {
138076f56faeSRakesh Ughreja 	struct hdac_bus *bus = dev_get_drvdata(component->dev);
1381bcc2a2dcSCezary Rojewski 	struct skl_dev *skl = bus_to_skl(bus);
138278cdbbdaSVinod Koul 	const struct skl_dsp_ops *ops;
1383fe3f4442SDharageswari R 	int ret;
1384b663a8c5SJeeja KP 
13857213170aSPierre-Louis Bossart 	ret = pm_runtime_resume_and_get(component->dev);
13867213170aSPierre-Louis Bossart 	if (ret < 0 && ret != -EACCES)
13877213170aSPierre-Louis Bossart 		return ret;
13887213170aSPierre-Louis Bossart 
138976f56faeSRakesh Ughreja 	if (bus->ppcap) {
139056b03b4cSKuninori Morimoto 		skl->component = component;
13915cdf6c09SVinod Koul 
13925cdf6c09SVinod Koul 		/* init debugfs */
13935cdf6c09SVinod Koul 		skl->debugfs = skl_debugfs_init(skl);
13945cdf6c09SVinod Koul 
139576f56faeSRakesh Ughreja 		ret = skl_tplg_init(component, bus);
1396fe3f4442SDharageswari R 		if (ret < 0) {
139756b03b4cSKuninori Morimoto 			dev_err(component->dev, "Failed to init topology!\n");
1398fe3f4442SDharageswari R 			return ret;
1399fe3f4442SDharageswari R 		}
140078cdbbdaSVinod Koul 
140178cdbbdaSVinod Koul 		/* load the firmwares, since all is set */
140278cdbbdaSVinod Koul 		ops = skl_get_dsp_ops(skl->pci->device);
140378cdbbdaSVinod Koul 		if (!ops)
140478cdbbdaSVinod Koul 			return -EIO;
140578cdbbdaSVinod Koul 
1406fc9fdd61SSanyog Kale 		/*
1407fc9fdd61SSanyog Kale 		 * Disable dynamic clock and power gating during firmware
1408fc9fdd61SSanyog Kale 		 * and library download
1409fc9fdd61SSanyog Kale 		 */
1410bcc2a2dcSCezary Rojewski 		skl->enable_miscbdcge(component->dev, false);
1411bcc2a2dcSCezary Rojewski 		skl->clock_power_gating(component->dev, false);
1412d5cc0a1fSPardha Saradhi K 
1413bcc2a2dcSCezary Rojewski 		ret = ops->init_fw(component->dev, skl);
1414bcc2a2dcSCezary Rojewski 		skl->enable_miscbdcge(component->dev, true);
1415bcc2a2dcSCezary Rojewski 		skl->clock_power_gating(component->dev, true);
141678cdbbdaSVinod Koul 		if (ret < 0) {
141756b03b4cSKuninori Morimoto 			dev_err(component->dev, "Failed to boot first fw: %d\n", ret);
141878cdbbdaSVinod Koul 			return ret;
141978cdbbdaSVinod Koul 		}
142064cb1d0aSVinod Koul 		skl_populate_modules(skl);
1421bcc2a2dcSCezary Rojewski 		skl->update_d0i3c = skl_update_d0i3c;
14229452314dSPradeep Tewani 
14239452314dSPradeep Tewani 		if (skl->cfg.astate_cfg != NULL) {
1424bcc2a2dcSCezary Rojewski 			skl_dsp_set_astate_cfg(skl,
14259452314dSPradeep Tewani 					skl->cfg.astate_cfg->count,
14269452314dSPradeep Tewani 					skl->cfg.astate_cfg);
14279452314dSPradeep Tewani 		}
142878cdbbdaSVinod Koul 	}
142956b03b4cSKuninori Morimoto 	pm_runtime_mark_last_busy(component->dev);
143056b03b4cSKuninori Morimoto 	pm_runtime_put_autosuspend(component->dev);
143178cdbbdaSVinod Koul 
1432b663a8c5SJeeja KP 	return 0;
1433b663a8c5SJeeja KP }
143456b03b4cSKuninori Morimoto 
skl_platform_soc_remove(struct snd_soc_component * component)14353507bb5fSKuninori Morimoto static void skl_platform_soc_remove(struct snd_soc_component *component)
14362e05ddd2SRanjani Sridharan {
1437e79986ceSAmadeusz Sławiński 	struct hdac_bus *bus = dev_get_drvdata(component->dev);
1438bcc2a2dcSCezary Rojewski 	struct skl_dev *skl = bus_to_skl(bus);
1439e79986ceSAmadeusz Sławiński 
1440e79986ceSAmadeusz Sławiński 	skl_tplg_exit(component, bus);
1441e79986ceSAmadeusz Sławiński 
1442e79986ceSAmadeusz Sławiński 	skl_debugfs_exit(skl);
14432e05ddd2SRanjani Sridharan }
14442e05ddd2SRanjani Sridharan 
144556b03b4cSKuninori Morimoto static const struct snd_soc_component_driver skl_component  = {
144656b03b4cSKuninori Morimoto 	.name		= "pcm",
1447b663a8c5SJeeja KP 	.probe		= skl_platform_soc_probe,
14483507bb5fSKuninori Morimoto 	.remove		= skl_platform_soc_remove,
14493507bb5fSKuninori Morimoto 	.open		= skl_platform_soc_open,
14503507bb5fSKuninori Morimoto 	.trigger	= skl_platform_soc_trigger,
14513507bb5fSKuninori Morimoto 	.pointer	= skl_platform_soc_pointer,
14523507bb5fSKuninori Morimoto 	.get_time_info	= skl_platform_soc_get_time_info,
14533507bb5fSKuninori Morimoto 	.pcm_construct	= skl_platform_soc_new,
1454b4ed6b51SRanjani Sridharan 	.module_get_upon_open = 1, /* increment refcount when a pcm is opened */
1455a40e693cSJeeja KP };
1456a40e693cSJeeja KP 
skl_platform_register(struct device * dev)1457a40e693cSJeeja KP int skl_platform_register(struct device *dev)
1458a40e693cSJeeja KP {
1459a40e693cSJeeja KP 	int ret;
1460c3ae22e3SGuneshwor Singh 	struct snd_soc_dai_driver *dais;
1461c3ae22e3SGuneshwor Singh 	int num_dais = ARRAY_SIZE(skl_platform_dai);
146276f56faeSRakesh Ughreja 	struct hdac_bus *bus = dev_get_drvdata(dev);
1463bcc2a2dcSCezary Rojewski 	struct skl_dev *skl = bus_to_skl(bus);
1464b663a8c5SJeeja KP 
1465c3ae22e3SGuneshwor Singh 	skl->dais = kmemdup(skl_platform_dai, sizeof(skl_platform_dai),
1466c3ae22e3SGuneshwor Singh 			    GFP_KERNEL);
1467c3ae22e3SGuneshwor Singh 	if (!skl->dais) {
1468c3ae22e3SGuneshwor Singh 		ret = -ENOMEM;
1469c3ae22e3SGuneshwor Singh 		goto err;
1470a40e693cSJeeja KP 	}
1471a40e693cSJeeja KP 
1472c3ae22e3SGuneshwor Singh 	if (!skl->use_tplg_pcm) {
1473c3ae22e3SGuneshwor Singh 		dais = krealloc(skl->dais, sizeof(skl_fe_dai) +
1474c3ae22e3SGuneshwor Singh 				sizeof(skl_platform_dai), GFP_KERNEL);
1475c3ae22e3SGuneshwor Singh 		if (!dais) {
1476*ab10ac26SKamil Duljas 			kfree(skl->dais);
1477c3ae22e3SGuneshwor Singh 			ret = -ENOMEM;
1478c3ae22e3SGuneshwor Singh 			goto err;
1479c3ae22e3SGuneshwor Singh 		}
1480c3ae22e3SGuneshwor Singh 
1481c3ae22e3SGuneshwor Singh 		skl->dais = dais;
1482c3ae22e3SGuneshwor Singh 		memcpy(&skl->dais[ARRAY_SIZE(skl_platform_dai)], skl_fe_dai,
1483c3ae22e3SGuneshwor Singh 		       sizeof(skl_fe_dai));
1484c3ae22e3SGuneshwor Singh 		num_dais += ARRAY_SIZE(skl_fe_dai);
1485c3ae22e3SGuneshwor Singh 	}
1486c3ae22e3SGuneshwor Singh 
148756b03b4cSKuninori Morimoto 	ret = devm_snd_soc_register_component(dev, &skl_component,
1488c3ae22e3SGuneshwor Singh 					 skl->dais, num_dais);
1489*ab10ac26SKamil Duljas 	if (ret) {
1490*ab10ac26SKamil Duljas 		kfree(skl->dais);
1491c3ae22e3SGuneshwor Singh 		dev_err(dev, "soc component registration failed %d\n", ret);
1492*ab10ac26SKamil Duljas 	}
1493c3ae22e3SGuneshwor Singh err:
1494a40e693cSJeeja KP 	return ret;
1495a40e693cSJeeja KP }
1496a40e693cSJeeja KP 
skl_platform_unregister(struct device * dev)1497a40e693cSJeeja KP int skl_platform_unregister(struct device *dev)
1498a40e693cSJeeja KP {
149976f56faeSRakesh Ughreja 	struct hdac_bus *bus = dev_get_drvdata(dev);
1500bcc2a2dcSCezary Rojewski 	struct skl_dev *skl = bus_to_skl(bus);
1501550b349aSDan Carpenter 	struct skl_module_deferred_bind *modules, *tmp;
1502b8c722ddSJeeja KP 
1503550b349aSDan Carpenter 	list_for_each_entry_safe(modules, tmp, &skl->bind_list, node) {
1504b8c722ddSJeeja KP 		list_del(&modules->node);
1505b8c722ddSJeeja KP 		kfree(modules);
1506b8c722ddSJeeja KP 	}
1507b8c722ddSJeeja KP 
1508c3ae22e3SGuneshwor Singh 	kfree(skl->dais);
1509c3ae22e3SGuneshwor Singh 
1510a40e693cSJeeja KP 	return 0;
1511a40e693cSJeeja KP }
1512