xref: /openbmc/linux/sound/soc/intel/skylake/skl-pcm.c (revision 8e8e69d6)
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>
16a40e693cSJeeja KP #include <sound/pcm_params.h>
17a40e693cSJeeja KP #include <sound/soc.h>
18a40e693cSJeeja KP #include "skl.h"
19b663a8c5SJeeja KP #include "skl-topology.h"
20721c3e36SDharageswari.R #include "skl-sst-dsp.h"
21721c3e36SDharageswari.R #include "skl-sst-ipc.h"
22a40e693cSJeeja KP 
23a40e693cSJeeja KP #define HDA_MONO 1
24a40e693cSJeeja KP #define HDA_STEREO 2
258f35bf3fSJeeja KP #define HDA_QUAD 4
263d178713SRakesh Ughreja #define HDA_MAX 8
27a40e693cSJeeja KP 
288df397ffSBhumika Goyal static const struct snd_pcm_hardware azx_pcm_hw = {
29a40e693cSJeeja KP 	.info =			(SNDRV_PCM_INFO_MMAP |
30a40e693cSJeeja KP 				 SNDRV_PCM_INFO_INTERLEAVED |
31a40e693cSJeeja KP 				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
32a40e693cSJeeja KP 				 SNDRV_PCM_INFO_MMAP_VALID |
33a40e693cSJeeja KP 				 SNDRV_PCM_INFO_PAUSE |
343637976bSJeeja KP 				 SNDRV_PCM_INFO_RESUME |
35a40e693cSJeeja KP 				 SNDRV_PCM_INFO_SYNC_START |
36a40e693cSJeeja KP 				 SNDRV_PCM_INFO_HAS_WALL_CLOCK | /* legacy */
37a40e693cSJeeja KP 				 SNDRV_PCM_INFO_HAS_LINK_ATIME |
38a40e693cSJeeja KP 				 SNDRV_PCM_INFO_NO_PERIOD_WAKEUP),
3906b23d93SJeeja KP 	.formats =		SNDRV_PCM_FMTBIT_S16_LE |
4006b23d93SJeeja KP 				SNDRV_PCM_FMTBIT_S32_LE |
4106b23d93SJeeja KP 				SNDRV_PCM_FMTBIT_S24_LE,
4206b23d93SJeeja KP 	.rates =		SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000 |
4306b23d93SJeeja KP 				SNDRV_PCM_RATE_8000,
4406b23d93SJeeja KP 	.rate_min =		8000,
45a40e693cSJeeja KP 	.rate_max =		48000,
468f35bf3fSJeeja KP 	.channels_min =		1,
477e12dc87SSubhransu S. Prusty 	.channels_max =		8,
48a40e693cSJeeja KP 	.buffer_bytes_max =	AZX_MAX_BUF_SIZE,
49a40e693cSJeeja KP 	.period_bytes_min =	128,
50a40e693cSJeeja KP 	.period_bytes_max =	AZX_MAX_BUF_SIZE / 2,
51a40e693cSJeeja KP 	.periods_min =		2,
52a40e693cSJeeja KP 	.periods_max =		AZX_MAX_FRAG,
53a40e693cSJeeja KP 	.fifo_size =		0,
54a40e693cSJeeja KP };
55a40e693cSJeeja KP 
56a40e693cSJeeja KP static inline
57a40e693cSJeeja KP struct hdac_ext_stream *get_hdac_ext_stream(struct snd_pcm_substream *substream)
58a40e693cSJeeja KP {
59a40e693cSJeeja KP 	return substream->runtime->private_data;
60a40e693cSJeeja KP }
61a40e693cSJeeja KP 
6276f56faeSRakesh Ughreja static struct hdac_bus *get_bus_ctx(struct snd_pcm_substream *substream)
63a40e693cSJeeja KP {
64a40e693cSJeeja KP 	struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
65a40e693cSJeeja KP 	struct hdac_stream *hstream = hdac_stream(stream);
66a40e693cSJeeja KP 	struct hdac_bus *bus = hstream->bus;
6776f56faeSRakesh Ughreja 	return bus;
68a40e693cSJeeja KP }
69a40e693cSJeeja KP 
7076f56faeSRakesh Ughreja static int skl_substream_alloc_pages(struct hdac_bus *bus,
71a40e693cSJeeja KP 				 struct snd_pcm_substream *substream,
72a40e693cSJeeja KP 				 size_t size)
73a40e693cSJeeja KP {
74a40e693cSJeeja KP 	struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
75a40e693cSJeeja KP 
76a40e693cSJeeja KP 	hdac_stream(stream)->bufsize = 0;
77a40e693cSJeeja KP 	hdac_stream(stream)->period_bytes = 0;
78a40e693cSJeeja KP 	hdac_stream(stream)->format_val = 0;
79a40e693cSJeeja KP 
80a40e693cSJeeja KP 	return snd_pcm_lib_malloc_pages(substream, size);
81a40e693cSJeeja KP }
82a40e693cSJeeja KP 
83a40e693cSJeeja KP static int skl_substream_free_pages(struct hdac_bus *bus,
84a40e693cSJeeja KP 				struct snd_pcm_substream *substream)
85a40e693cSJeeja KP {
86a40e693cSJeeja KP 	return snd_pcm_lib_free_pages(substream);
87a40e693cSJeeja KP }
88a40e693cSJeeja KP 
8976f56faeSRakesh Ughreja static void skl_set_pcm_constrains(struct hdac_bus *bus,
90a40e693cSJeeja KP 				 struct snd_pcm_runtime *runtime)
91a40e693cSJeeja KP {
92a40e693cSJeeja KP 	snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
93a40e693cSJeeja KP 
94a40e693cSJeeja KP 	/* avoid wrap-around with wall-clock */
95a40e693cSJeeja KP 	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_TIME,
96a40e693cSJeeja KP 				     20, 178000000);
97a40e693cSJeeja KP }
98a40e693cSJeeja KP 
9976f56faeSRakesh Ughreja static enum hdac_ext_stream_type skl_get_host_stream_type(struct hdac_bus *bus)
10005057001SJeeja KP {
10176f56faeSRakesh Ughreja 	if (bus->ppcap)
10205057001SJeeja KP 		return HDAC_EXT_STREAM_TYPE_HOST;
10305057001SJeeja KP 	else
10405057001SJeeja KP 		return HDAC_EXT_STREAM_TYPE_COUPLED;
10505057001SJeeja KP }
10605057001SJeeja KP 
1074557c305SJeeja KP /*
1084557c305SJeeja KP  * check if the stream opened is marked as ignore_suspend by machine, if so
1094557c305SJeeja KP  * then enable suspend_active refcount
1104557c305SJeeja KP  *
1114557c305SJeeja KP  * The count supend_active does not need lock as it is used in open/close
1124557c305SJeeja KP  * and suspend context
1134557c305SJeeja KP  */
1144557c305SJeeja KP static void skl_set_suspend_active(struct snd_pcm_substream *substream,
1154557c305SJeeja KP 					 struct snd_soc_dai *dai, bool enable)
1164557c305SJeeja KP {
11776f56faeSRakesh Ughreja 	struct hdac_bus *bus = dev_get_drvdata(dai->dev);
1184557c305SJeeja KP 	struct snd_soc_dapm_widget *w;
11976f56faeSRakesh Ughreja 	struct skl *skl = bus_to_skl(bus);
1204557c305SJeeja KP 
1214557c305SJeeja KP 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
1224557c305SJeeja KP 		w = dai->playback_widget;
1234557c305SJeeja KP 	else
1244557c305SJeeja KP 		w = dai->capture_widget;
1254557c305SJeeja KP 
1264557c305SJeeja KP 	if (w->ignore_suspend && enable)
1274557c305SJeeja KP 		skl->supend_active++;
1284557c305SJeeja KP 	else if (w->ignore_suspend && !enable)
1294557c305SJeeja KP 		skl->supend_active--;
1304557c305SJeeja KP }
1314557c305SJeeja KP 
132ad036bdeSJeeja KP int skl_pcm_host_dma_prepare(struct device *dev, struct skl_pipe_params *params)
133ad036bdeSJeeja KP {
13476f56faeSRakesh Ughreja 	struct hdac_bus *bus = dev_get_drvdata(dev);
135ad036bdeSJeeja KP 	unsigned int format_val;
136ad036bdeSJeeja KP 	struct hdac_stream *hstream;
137ad036bdeSJeeja KP 	struct hdac_ext_stream *stream;
138ad036bdeSJeeja KP 	int err;
139ad036bdeSJeeja KP 
140ad036bdeSJeeja KP 	hstream = snd_hdac_get_stream(bus, params->stream,
141ad036bdeSJeeja KP 					params->host_dma_id + 1);
142ad036bdeSJeeja KP 	if (!hstream)
143ad036bdeSJeeja KP 		return -EINVAL;
144ad036bdeSJeeja KP 
145ad036bdeSJeeja KP 	stream = stream_to_hdac_ext_stream(hstream);
14676f56faeSRakesh Ughreja 	snd_hdac_ext_stream_decouple(bus, stream, true);
147ad036bdeSJeeja KP 
148ad036bdeSJeeja KP 	format_val = snd_hdac_calc_stream_format(params->s_freq,
1497f975a38SJeeja KP 			params->ch, params->format, params->host_bps, 0);
150ad036bdeSJeeja KP 
151ad036bdeSJeeja KP 	dev_dbg(dev, "format_val=%d, rate=%d, ch=%d, format=%d\n",
152ad036bdeSJeeja KP 		format_val, params->s_freq, params->ch, params->format);
153ad036bdeSJeeja KP 
154ad036bdeSJeeja KP 	snd_hdac_stream_reset(hdac_stream(stream));
155ad036bdeSJeeja KP 	err = snd_hdac_stream_set_params(hdac_stream(stream), format_val);
156ad036bdeSJeeja KP 	if (err < 0)
157ad036bdeSJeeja KP 		return err;
158ad036bdeSJeeja KP 
159ad036bdeSJeeja KP 	err = snd_hdac_stream_setup(hdac_stream(stream));
160ad036bdeSJeeja KP 	if (err < 0)
161ad036bdeSJeeja KP 		return err;
162ad036bdeSJeeja KP 
163ad036bdeSJeeja KP 	hdac_stream(stream)->prepared = 1;
164ad036bdeSJeeja KP 
165ad036bdeSJeeja KP 	return 0;
166ad036bdeSJeeja KP }
167ad036bdeSJeeja KP 
168ad036bdeSJeeja KP int skl_pcm_link_dma_prepare(struct device *dev, struct skl_pipe_params *params)
169ad036bdeSJeeja KP {
17076f56faeSRakesh Ughreja 	struct hdac_bus *bus = dev_get_drvdata(dev);
171ad036bdeSJeeja KP 	unsigned int format_val;
172ad036bdeSJeeja KP 	struct hdac_stream *hstream;
173ad036bdeSJeeja KP 	struct hdac_ext_stream *stream;
174ad036bdeSJeeja KP 	struct hdac_ext_link *link;
175c899df3eSRander Wang 	unsigned char stream_tag;
176ad036bdeSJeeja KP 
177ad036bdeSJeeja KP 	hstream = snd_hdac_get_stream(bus, params->stream,
178ad036bdeSJeeja KP 					params->link_dma_id + 1);
179ad036bdeSJeeja KP 	if (!hstream)
180ad036bdeSJeeja KP 		return -EINVAL;
181ad036bdeSJeeja KP 
182ad036bdeSJeeja KP 	stream = stream_to_hdac_ext_stream(hstream);
18376f56faeSRakesh Ughreja 	snd_hdac_ext_stream_decouple(bus, stream, true);
1847f975a38SJeeja KP 	format_val = snd_hdac_calc_stream_format(params->s_freq, params->ch,
1857f975a38SJeeja KP 					params->format, params->link_bps, 0);
186ad036bdeSJeeja KP 
187ad036bdeSJeeja KP 	dev_dbg(dev, "format_val=%d, rate=%d, ch=%d, format=%d\n",
188ad036bdeSJeeja KP 		format_val, params->s_freq, params->ch, params->format);
189ad036bdeSJeeja KP 
190ad036bdeSJeeja KP 	snd_hdac_ext_link_stream_reset(stream);
191ad036bdeSJeeja KP 
192ad036bdeSJeeja KP 	snd_hdac_ext_link_stream_setup(stream, format_val);
193ad036bdeSJeeja KP 
194c899df3eSRander Wang 	stream_tag = hstream->stream_tag;
195c899df3eSRander Wang 	if (stream->hstream.direction == SNDRV_PCM_STREAM_PLAYBACK) {
19676f56faeSRakesh Ughreja 		list_for_each_entry(link, &bus->hlink_list, list) {
197ad036bdeSJeeja KP 			if (link->index == params->link_index)
198ad036bdeSJeeja KP 				snd_hdac_ext_link_set_stream_id(link,
199c899df3eSRander Wang 								stream_tag);
200c899df3eSRander Wang 		}
201ad036bdeSJeeja KP 	}
202ad036bdeSJeeja KP 
203ad036bdeSJeeja KP 	stream->link_prepared = 1;
204ad036bdeSJeeja KP 
205ad036bdeSJeeja KP 	return 0;
206ad036bdeSJeeja KP }
207ad036bdeSJeeja KP 
208a40e693cSJeeja KP static int skl_pcm_open(struct snd_pcm_substream *substream,
209a40e693cSJeeja KP 		struct snd_soc_dai *dai)
210a40e693cSJeeja KP {
21176f56faeSRakesh Ughreja 	struct hdac_bus *bus = dev_get_drvdata(dai->dev);
212a40e693cSJeeja KP 	struct hdac_ext_stream *stream;
213a40e693cSJeeja KP 	struct snd_pcm_runtime *runtime = substream->runtime;
214a40e693cSJeeja KP 	struct skl_dma_params *dma_params;
215a83e3b4cSVinod Koul 	struct skl *skl = get_skl_ctx(dai->dev);
216a83e3b4cSVinod Koul 	struct skl_module_cfg *mconfig;
217a40e693cSJeeja KP 
218a40e693cSJeeja KP 	dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
219a40e693cSJeeja KP 
22076f56faeSRakesh Ughreja 	stream = snd_hdac_ext_stream_assign(bus, substream,
22176f56faeSRakesh Ughreja 					skl_get_host_stream_type(bus));
222a40e693cSJeeja KP 	if (stream == NULL)
223a40e693cSJeeja KP 		return -EBUSY;
224a40e693cSJeeja KP 
22576f56faeSRakesh Ughreja 	skl_set_pcm_constrains(bus, runtime);
226a40e693cSJeeja KP 
227a40e693cSJeeja KP 	/*
228a40e693cSJeeja KP 	 * disable WALLCLOCK timestamps for capture streams
229a40e693cSJeeja KP 	 * until we figure out how to handle digital inputs
230a40e693cSJeeja KP 	 */
231a40e693cSJeeja KP 	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
232a40e693cSJeeja KP 		runtime->hw.info &= ~SNDRV_PCM_INFO_HAS_WALL_CLOCK; /* legacy */
233a40e693cSJeeja KP 		runtime->hw.info &= ~SNDRV_PCM_INFO_HAS_LINK_ATIME;
234a40e693cSJeeja KP 	}
235a40e693cSJeeja KP 
236a40e693cSJeeja KP 	runtime->private_data = stream;
237a40e693cSJeeja KP 
238a40e693cSJeeja KP 	dma_params = kzalloc(sizeof(*dma_params), GFP_KERNEL);
239a40e693cSJeeja KP 	if (!dma_params)
240a40e693cSJeeja KP 		return -ENOMEM;
241a40e693cSJeeja KP 
242a40e693cSJeeja KP 	dma_params->stream_tag = hdac_stream(stream)->stream_tag;
243a40e693cSJeeja KP 	snd_soc_dai_set_dma_data(dai, substream, dma_params);
244a40e693cSJeeja KP 
245a40e693cSJeeja KP 	dev_dbg(dai->dev, "stream tag set in dma params=%d\n",
246a40e693cSJeeja KP 				 dma_params->stream_tag);
2474557c305SJeeja KP 	skl_set_suspend_active(substream, dai, true);
248a40e693cSJeeja KP 	snd_pcm_set_sync(substream);
249a40e693cSJeeja KP 
250a83e3b4cSVinod Koul 	mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream);
25191ce5497SG Kranthi 	if (!mconfig)
25291ce5497SG Kranthi 		return -EINVAL;
25391ce5497SG Kranthi 
254a83e3b4cSVinod Koul 	skl_tplg_d0i3_get(skl, mconfig->d0i3_caps);
255a83e3b4cSVinod Koul 
256a40e693cSJeeja KP 	return 0;
257a40e693cSJeeja KP }
258a40e693cSJeeja KP 
259a40e693cSJeeja KP static int skl_pcm_prepare(struct snd_pcm_substream *substream,
260a40e693cSJeeja KP 		struct snd_soc_dai *dai)
261a40e693cSJeeja KP {
2622004432fSJeeja KP 	struct skl *skl = get_skl_ctx(dai->dev);
2632004432fSJeeja KP 	struct skl_module_cfg *mconfig;
26474e65192SPardha Saradhi K 	int ret;
265a40e693cSJeeja KP 
266a40e693cSJeeja KP 	dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
267a40e693cSJeeja KP 
2682004432fSJeeja KP 	mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream);
2692004432fSJeeja KP 
27074e65192SPardha Saradhi K 	/*
27174e65192SPardha Saradhi K 	 * In case of XRUN recovery or in the case when the application
27274e65192SPardha Saradhi K 	 * calls prepare another time, reset the FW pipe to clean state
27374e65192SPardha Saradhi K 	 */
27474e65192SPardha Saradhi K 	if (mconfig &&
27574e65192SPardha Saradhi K 		(substream->runtime->status->state == SNDRV_PCM_STATE_XRUN ||
27674e65192SPardha Saradhi K 		 mconfig->pipe->state == SKL_PIPE_CREATED ||
27774e65192SPardha Saradhi K 		 mconfig->pipe->state == SKL_PIPE_PAUSED)) {
27874e65192SPardha Saradhi K 
27974e65192SPardha Saradhi K 		ret = skl_reset_pipe(skl->skl_sst, mconfig->pipe);
28074e65192SPardha Saradhi K 
28174e65192SPardha Saradhi K 		if (ret < 0)
28274e65192SPardha Saradhi K 			return ret;
28374e65192SPardha Saradhi K 
28474e65192SPardha Saradhi K 		ret = skl_pcm_host_dma_prepare(dai->dev,
28574e65192SPardha Saradhi K 					mconfig->pipe->p_params);
28674e65192SPardha Saradhi K 		if (ret < 0)
28774e65192SPardha Saradhi K 			return ret;
28874e65192SPardha Saradhi K 	}
2892004432fSJeeja KP 
290bb704a73SJeeja KP 	return 0;
291a40e693cSJeeja KP }
292a40e693cSJeeja KP 
293a40e693cSJeeja KP static int skl_pcm_hw_params(struct snd_pcm_substream *substream,
294a40e693cSJeeja KP 				struct snd_pcm_hw_params *params,
295a40e693cSJeeja KP 				struct snd_soc_dai *dai)
296a40e693cSJeeja KP {
29776f56faeSRakesh Ughreja 	struct hdac_bus *bus = dev_get_drvdata(dai->dev);
29805057001SJeeja KP 	struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
299a40e693cSJeeja KP 	struct snd_pcm_runtime *runtime = substream->runtime;
300b663a8c5SJeeja KP 	struct skl_pipe_params p_params = {0};
301b663a8c5SJeeja KP 	struct skl_module_cfg *m_cfg;
30205057001SJeeja KP 	int ret, dma_id;
303a40e693cSJeeja KP 
304a40e693cSJeeja KP 	dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
30576f56faeSRakesh Ughreja 	ret = skl_substream_alloc_pages(bus, substream,
306a40e693cSJeeja KP 					  params_buffer_bytes(params));
307a40e693cSJeeja KP 	if (ret < 0)
308a40e693cSJeeja KP 		return ret;
309a40e693cSJeeja KP 
310a40e693cSJeeja KP 	dev_dbg(dai->dev, "format_val, rate=%d, ch=%d, format=%d\n",
311a40e693cSJeeja KP 			runtime->rate, runtime->channels, runtime->format);
312a40e693cSJeeja KP 
31305057001SJeeja KP 	dma_id = hdac_stream(stream)->stream_tag - 1;
31405057001SJeeja KP 	dev_dbg(dai->dev, "dma_id=%d\n", dma_id);
31505057001SJeeja KP 
316b663a8c5SJeeja KP 	p_params.s_fmt = snd_pcm_format_width(params_format(params));
317b663a8c5SJeeja KP 	p_params.ch = params_channels(params);
318b663a8c5SJeeja KP 	p_params.s_freq = params_rate(params);
319b663a8c5SJeeja KP 	p_params.host_dma_id = dma_id;
320b663a8c5SJeeja KP 	p_params.stream = substream->stream;
32112c3be0eSJeeja KP 	p_params.format = params_format(params);
3227f975a38SJeeja KP 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
3237f975a38SJeeja KP 		p_params.host_bps = dai->driver->playback.sig_bits;
3247f975a38SJeeja KP 	else
3257f975a38SJeeja KP 		p_params.host_bps = dai->driver->capture.sig_bits;
3267f975a38SJeeja KP 
327b663a8c5SJeeja KP 
328b663a8c5SJeeja KP 	m_cfg = skl_tplg_fe_get_cpr_module(dai, p_params.stream);
329b663a8c5SJeeja KP 	if (m_cfg)
330b663a8c5SJeeja KP 		skl_tplg_update_pipe_params(dai->dev, m_cfg, &p_params);
331b663a8c5SJeeja KP 
332a40e693cSJeeja KP 	return 0;
333a40e693cSJeeja KP }
334a40e693cSJeeja KP 
335a40e693cSJeeja KP static void skl_pcm_close(struct snd_pcm_substream *substream,
336a40e693cSJeeja KP 		struct snd_soc_dai *dai)
337a40e693cSJeeja KP {
338a40e693cSJeeja KP 	struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
33976f56faeSRakesh Ughreja 	struct hdac_bus *bus = dev_get_drvdata(dai->dev);
340a40e693cSJeeja KP 	struct skl_dma_params *dma_params = NULL;
34176f56faeSRakesh Ughreja 	struct skl *skl = bus_to_skl(bus);
342a83e3b4cSVinod Koul 	struct skl_module_cfg *mconfig;
343a40e693cSJeeja KP 
344a40e693cSJeeja KP 	dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
34505057001SJeeja KP 
34676f56faeSRakesh Ughreja 	snd_hdac_ext_stream_release(stream, skl_get_host_stream_type(bus));
347a40e693cSJeeja KP 
348a40e693cSJeeja KP 	dma_params = snd_soc_dai_get_dma_data(dai, substream);
349a40e693cSJeeja KP 	/*
350a40e693cSJeeja KP 	 * now we should set this to NULL as we are freeing by the
351a40e693cSJeeja KP 	 * dma_params
352a40e693cSJeeja KP 	 */
353a40e693cSJeeja KP 	snd_soc_dai_set_dma_data(dai, substream, NULL);
3544557c305SJeeja KP 	skl_set_suspend_active(substream, dai, false);
355a40e693cSJeeja KP 
356721c3e36SDharageswari.R 	/*
357721c3e36SDharageswari.R 	 * check if close is for "Reference Pin" and set back the
358721c3e36SDharageswari.R 	 * CGCTL.MISCBDCGE if disabled by driver
359721c3e36SDharageswari.R 	 */
360721c3e36SDharageswari.R 	if (!strncmp(dai->name, "Reference Pin", 13) &&
361721c3e36SDharageswari.R 			skl->skl_sst->miscbdcg_disabled) {
362721c3e36SDharageswari.R 		skl->skl_sst->enable_miscbdcge(dai->dev, true);
363721c3e36SDharageswari.R 		skl->skl_sst->miscbdcg_disabled = false;
364721c3e36SDharageswari.R 	}
365721c3e36SDharageswari.R 
366a83e3b4cSVinod Koul 	mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream);
3670265ddd7SPankaj Bharadiya 	if (mconfig)
368a83e3b4cSVinod Koul 		skl_tplg_d0i3_put(skl, mconfig->d0i3_caps);
369a83e3b4cSVinod Koul 
370a40e693cSJeeja KP 	kfree(dma_params);
371a40e693cSJeeja KP }
372a40e693cSJeeja KP 
373a40e693cSJeeja KP static int skl_pcm_hw_free(struct snd_pcm_substream *substream,
374a40e693cSJeeja KP 		struct snd_soc_dai *dai)
375a40e693cSJeeja KP {
37676f56faeSRakesh Ughreja 	struct hdac_bus *bus = dev_get_drvdata(dai->dev);
377a40e693cSJeeja KP 	struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
378179c2e86SDivya Prakash 	struct skl *skl = get_skl_ctx(dai->dev);
379179c2e86SDivya Prakash 	struct skl_module_cfg *mconfig;
380179c2e86SDivya Prakash 	int ret;
381a40e693cSJeeja KP 
382a40e693cSJeeja KP 	dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
383a40e693cSJeeja KP 
384179c2e86SDivya Prakash 	mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream);
385179c2e86SDivya Prakash 
386179c2e86SDivya Prakash 	if (mconfig) {
387179c2e86SDivya Prakash 		ret = skl_reset_pipe(skl->skl_sst, mconfig->pipe);
388179c2e86SDivya Prakash 		if (ret < 0)
389179c2e86SDivya Prakash 			dev_err(dai->dev, "%s:Reset failed ret =%d",
390179c2e86SDivya Prakash 						__func__, ret);
391179c2e86SDivya Prakash 	}
392179c2e86SDivya Prakash 
393a40e693cSJeeja KP 	snd_hdac_stream_cleanup(hdac_stream(stream));
394a40e693cSJeeja KP 	hdac_stream(stream)->prepared = 0;
395a40e693cSJeeja KP 
39676f56faeSRakesh Ughreja 	return skl_substream_free_pages(bus, substream);
397a40e693cSJeeja KP }
398a40e693cSJeeja KP 
399b663a8c5SJeeja KP static int skl_be_hw_params(struct snd_pcm_substream *substream,
400b663a8c5SJeeja KP 				struct snd_pcm_hw_params *params,
401b663a8c5SJeeja KP 				struct snd_soc_dai *dai)
402b663a8c5SJeeja KP {
403b663a8c5SJeeja KP 	struct skl_pipe_params p_params = {0};
404b663a8c5SJeeja KP 
405b663a8c5SJeeja KP 	p_params.s_fmt = snd_pcm_format_width(params_format(params));
406b663a8c5SJeeja KP 	p_params.ch = params_channels(params);
407b663a8c5SJeeja KP 	p_params.s_freq = params_rate(params);
408b663a8c5SJeeja KP 	p_params.stream = substream->stream;
409b663a8c5SJeeja KP 
4104bd073f9SJeeja KP 	return skl_tplg_be_update_params(dai, &p_params);
411b663a8c5SJeeja KP }
412b663a8c5SJeeja KP 
413d1730c3dSJeeja KP static int skl_decoupled_trigger(struct snd_pcm_substream *substream,
414d1730c3dSJeeja KP 		int cmd)
415d1730c3dSJeeja KP {
41676f56faeSRakesh Ughreja 	struct hdac_bus *bus = get_bus_ctx(substream);
417d1730c3dSJeeja KP 	struct hdac_ext_stream *stream;
418d1730c3dSJeeja KP 	int start;
419d1730c3dSJeeja KP 	unsigned long cookie;
420d1730c3dSJeeja KP 	struct hdac_stream *hstr;
421d1730c3dSJeeja KP 
422d1730c3dSJeeja KP 	stream = get_hdac_ext_stream(substream);
423d1730c3dSJeeja KP 	hstr = hdac_stream(stream);
424d1730c3dSJeeja KP 
425d1730c3dSJeeja KP 	if (!hstr->prepared)
426d1730c3dSJeeja KP 		return -EPIPE;
427d1730c3dSJeeja KP 
428d1730c3dSJeeja KP 	switch (cmd) {
429d1730c3dSJeeja KP 	case SNDRV_PCM_TRIGGER_START:
430d1730c3dSJeeja KP 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
431d1730c3dSJeeja KP 	case SNDRV_PCM_TRIGGER_RESUME:
432d1730c3dSJeeja KP 		start = 1;
433d1730c3dSJeeja KP 		break;
434d1730c3dSJeeja KP 
435d1730c3dSJeeja KP 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
436d1730c3dSJeeja KP 	case SNDRV_PCM_TRIGGER_SUSPEND:
437d1730c3dSJeeja KP 	case SNDRV_PCM_TRIGGER_STOP:
438d1730c3dSJeeja KP 		start = 0;
439d1730c3dSJeeja KP 		break;
440d1730c3dSJeeja KP 
441d1730c3dSJeeja KP 	default:
442d1730c3dSJeeja KP 		return -EINVAL;
443d1730c3dSJeeja KP 	}
444d1730c3dSJeeja KP 
445d1730c3dSJeeja KP 	spin_lock_irqsave(&bus->reg_lock, cookie);
446d1730c3dSJeeja KP 
447d1730c3dSJeeja KP 	if (start) {
448d1730c3dSJeeja KP 		snd_hdac_stream_start(hdac_stream(stream), true);
449d1730c3dSJeeja KP 		snd_hdac_stream_timecounter_init(hstr, 0);
450d1730c3dSJeeja KP 	} else {
451d1730c3dSJeeja KP 		snd_hdac_stream_stop(hdac_stream(stream));
452d1730c3dSJeeja KP 	}
453d1730c3dSJeeja KP 
454d1730c3dSJeeja KP 	spin_unlock_irqrestore(&bus->reg_lock, cookie);
455d1730c3dSJeeja KP 
456d1730c3dSJeeja KP 	return 0;
457d1730c3dSJeeja KP }
458d1730c3dSJeeja KP 
459b663a8c5SJeeja KP static int skl_pcm_trigger(struct snd_pcm_substream *substream, int cmd,
460b663a8c5SJeeja KP 		struct snd_soc_dai *dai)
461b663a8c5SJeeja KP {
462b663a8c5SJeeja KP 	struct skl *skl = get_skl_ctx(dai->dev);
463b663a8c5SJeeja KP 	struct skl_sst *ctx = skl->skl_sst;
464b663a8c5SJeeja KP 	struct skl_module_cfg *mconfig;
46576f56faeSRakesh Ughreja 	struct hdac_bus *bus = get_bus_ctx(substream);
4667e3a17d3SJeeja KP 	struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
4679a655db0SJeeja KP 	struct snd_soc_dapm_widget *w;
468d1730c3dSJeeja KP 	int ret;
469b663a8c5SJeeja KP 
470b663a8c5SJeeja KP 	mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream);
471b663a8c5SJeeja KP 	if (!mconfig)
472b663a8c5SJeeja KP 		return -EIO;
473b663a8c5SJeeja KP 
4749a655db0SJeeja KP 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
4759a655db0SJeeja KP 		w = dai->playback_widget;
4769a655db0SJeeja KP 	else
4779a655db0SJeeja KP 		w = dai->capture_widget;
4789a655db0SJeeja KP 
479b663a8c5SJeeja KP 	switch (cmd) {
4807e3a17d3SJeeja KP 	case SNDRV_PCM_TRIGGER_RESUME:
4819a655db0SJeeja KP 		if (!w->ignore_suspend) {
482748a1d5aSJeeja KP 			/*
4839a655db0SJeeja KP 			 * enable DMA Resume enable bit for the stream, set the
4849a655db0SJeeja KP 			 * dpib & lpib position to resume before starting the
4859a655db0SJeeja KP 			 * DMA
486748a1d5aSJeeja KP 			 */
48776f56faeSRakesh Ughreja 			snd_hdac_ext_stream_drsm_enable(bus, true,
488748a1d5aSJeeja KP 						hdac_stream(stream)->index);
48976f56faeSRakesh Ughreja 			snd_hdac_ext_stream_set_dpibr(bus, stream,
490a700a1e6SJeeja KP 							stream->lpib);
491748a1d5aSJeeja KP 			snd_hdac_ext_stream_set_lpib(stream, stream->lpib);
4929a655db0SJeeja KP 		}
493e4bfd615STakashi Iwai 		/* fall through */
494748a1d5aSJeeja KP 
495d1730c3dSJeeja KP 	case SNDRV_PCM_TRIGGER_START:
496b663a8c5SJeeja KP 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
497d1730c3dSJeeja KP 		/*
498d1730c3dSJeeja KP 		 * Start HOST DMA and Start FE Pipe.This is to make sure that
499d1730c3dSJeeja KP 		 * there are no underrun/overrun in the case when the FE
500d1730c3dSJeeja KP 		 * pipeline is started but there is a delay in starting the
501d1730c3dSJeeja KP 		 * DMA channel on the host.
502d1730c3dSJeeja KP 		 */
503d1730c3dSJeeja KP 		ret = skl_decoupled_trigger(substream, cmd);
504d1730c3dSJeeja KP 		if (ret < 0)
505d1730c3dSJeeja KP 			return ret;
506b663a8c5SJeeja KP 		return skl_run_pipe(ctx, mconfig->pipe);
507d1730c3dSJeeja KP 		break;
508b663a8c5SJeeja KP 
509b663a8c5SJeeja KP 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
510b663a8c5SJeeja KP 	case SNDRV_PCM_TRIGGER_SUSPEND:
511d1730c3dSJeeja KP 	case SNDRV_PCM_TRIGGER_STOP:
512d1730c3dSJeeja KP 		/*
513d1730c3dSJeeja KP 		 * Stop FE Pipe first and stop DMA. This is to make sure that
514d1730c3dSJeeja KP 		 * there are no underrun/overrun in the case if there is a delay
515d1730c3dSJeeja KP 		 * between the two operations.
516d1730c3dSJeeja KP 		 */
517d1730c3dSJeeja KP 		ret = skl_stop_pipe(ctx, mconfig->pipe);
518d1730c3dSJeeja KP 		if (ret < 0)
519d1730c3dSJeeja KP 			return ret;
520d1730c3dSJeeja KP 
521d1730c3dSJeeja KP 		ret = skl_decoupled_trigger(substream, cmd);
5229a655db0SJeeja KP 		if ((cmd == SNDRV_PCM_TRIGGER_SUSPEND) && !w->ignore_suspend) {
523748a1d5aSJeeja KP 			/* save the dpib and lpib positions */
52476f56faeSRakesh Ughreja 			stream->dpib = readl(bus->remap_addr +
525748a1d5aSJeeja KP 					AZX_REG_VS_SDXDPIB_XBASE +
526748a1d5aSJeeja KP 					(AZX_REG_VS_SDXDPIB_XINTERVAL *
527748a1d5aSJeeja KP 					hdac_stream(stream)->index));
528748a1d5aSJeeja KP 
529748a1d5aSJeeja KP 			stream->lpib = snd_hdac_stream_get_pos_lpib(
530748a1d5aSJeeja KP 							hdac_stream(stream));
53176f56faeSRakesh Ughreja 			snd_hdac_ext_stream_decouple(bus, stream, false);
532748a1d5aSJeeja KP 		}
533d1730c3dSJeeja KP 		break;
534b663a8c5SJeeja KP 
535b663a8c5SJeeja KP 	default:
536d1730c3dSJeeja KP 		return -EINVAL;
537b663a8c5SJeeja KP 	}
538d1730c3dSJeeja KP 
539d1730c3dSJeeja KP 	return 0;
540b663a8c5SJeeja KP }
541b663a8c5SJeeja KP 
54276f56faeSRakesh Ughreja 
54305057001SJeeja KP static int skl_link_hw_params(struct snd_pcm_substream *substream,
54405057001SJeeja KP 				struct snd_pcm_hw_params *params,
54505057001SJeeja KP 				struct snd_soc_dai *dai)
54605057001SJeeja KP {
54776f56faeSRakesh Ughreja 	struct hdac_bus *bus = dev_get_drvdata(dai->dev);
54805057001SJeeja KP 	struct hdac_ext_stream *link_dev;
54905057001SJeeja KP 	struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
55005057001SJeeja KP 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
551b663a8c5SJeeja KP 	struct skl_pipe_params p_params = {0};
55212c3be0eSJeeja KP 	struct hdac_ext_link *link;
5531011509dSJeeja KP 	int stream_tag;
55405057001SJeeja KP 
55576f56faeSRakesh Ughreja 	link_dev = snd_hdac_ext_stream_assign(bus, substream,
55605057001SJeeja KP 					HDAC_EXT_STREAM_TYPE_LINK);
55705057001SJeeja KP 	if (!link_dev)
55805057001SJeeja KP 		return -EBUSY;
55905057001SJeeja KP 
56005057001SJeeja KP 	snd_soc_dai_set_dma_data(dai, substream, (void *)link_dev);
56105057001SJeeja KP 
56276f56faeSRakesh Ughreja 	link = snd_hdac_ext_bus_get_link(bus, codec_dai->component->name);
56312c3be0eSJeeja KP 	if (!link)
56412c3be0eSJeeja KP 		return -EINVAL;
56512c3be0eSJeeja KP 
5661011509dSJeeja KP 	stream_tag = hdac_stream(link_dev)->stream_tag;
5671011509dSJeeja KP 
56805057001SJeeja KP 	/* set the stream tag in the codec dai dma params  */
5693d178713SRakesh Ughreja 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
5701011509dSJeeja KP 		snd_soc_dai_set_tdm_slot(codec_dai, stream_tag, 0, 0, 0);
5713d178713SRakesh Ughreja 	else
5723d178713SRakesh Ughreja 		snd_soc_dai_set_tdm_slot(codec_dai, 0, stream_tag, 0, 0);
573b663a8c5SJeeja KP 
574b663a8c5SJeeja KP 	p_params.s_fmt = snd_pcm_format_width(params_format(params));
575b663a8c5SJeeja KP 	p_params.ch = params_channels(params);
576b663a8c5SJeeja KP 	p_params.s_freq = params_rate(params);
577b663a8c5SJeeja KP 	p_params.stream = substream->stream;
5781011509dSJeeja KP 	p_params.link_dma_id = stream_tag - 1;
57912c3be0eSJeeja KP 	p_params.link_index = link->index;
58012c3be0eSJeeja KP 	p_params.format = params_format(params);
581b663a8c5SJeeja KP 
5827f975a38SJeeja KP 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
5837f975a38SJeeja KP 		p_params.link_bps = codec_dai->driver->playback.sig_bits;
5847f975a38SJeeja KP 	else
5857f975a38SJeeja KP 		p_params.link_bps = codec_dai->driver->capture.sig_bits;
5867f975a38SJeeja KP 
5874bd073f9SJeeja KP 	return skl_tplg_be_update_params(dai, &p_params);
58805057001SJeeja KP }
58905057001SJeeja KP 
59005057001SJeeja KP static int skl_link_pcm_prepare(struct snd_pcm_substream *substream,
59105057001SJeeja KP 		struct snd_soc_dai *dai)
59205057001SJeeja KP {
5932004432fSJeeja KP 	struct skl *skl = get_skl_ctx(dai->dev);
5942004432fSJeeja KP 	struct skl_module_cfg *mconfig = NULL;
59505057001SJeeja KP 
5962004432fSJeeja KP 	/* In case of XRUN recovery, reset the FW pipe to clean state */
5972004432fSJeeja KP 	mconfig = skl_tplg_be_get_cpr_module(dai, substream->stream);
5987cbfdf87SJeeja KP 	if (mconfig && !mconfig->pipe->passthru &&
5997cbfdf87SJeeja KP 		(substream->runtime->status->state == SNDRV_PCM_STATE_XRUN))
6002004432fSJeeja KP 		skl_reset_pipe(skl->skl_sst, mconfig->pipe);
6012004432fSJeeja KP 
60205057001SJeeja KP 	return 0;
60305057001SJeeja KP }
60405057001SJeeja KP 
60505057001SJeeja KP static int skl_link_pcm_trigger(struct snd_pcm_substream *substream,
60605057001SJeeja KP 	int cmd, struct snd_soc_dai *dai)
60705057001SJeeja KP {
60805057001SJeeja KP 	struct hdac_ext_stream *link_dev =
60905057001SJeeja KP 				snd_soc_dai_get_dma_data(dai, substream);
61076f56faeSRakesh Ughreja 	struct hdac_bus *bus = get_bus_ctx(substream);
611920982c9SJeeja KP 	struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
61205057001SJeeja KP 
61305057001SJeeja KP 	dev_dbg(dai->dev, "In %s cmd=%d\n", __func__, cmd);
61405057001SJeeja KP 	switch (cmd) {
615920982c9SJeeja KP 	case SNDRV_PCM_TRIGGER_RESUME:
61605057001SJeeja KP 	case SNDRV_PCM_TRIGGER_START:
61705057001SJeeja KP 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
61805057001SJeeja KP 		snd_hdac_ext_link_stream_start(link_dev);
61905057001SJeeja KP 		break;
62005057001SJeeja KP 
62105057001SJeeja KP 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
62205057001SJeeja KP 	case SNDRV_PCM_TRIGGER_SUSPEND:
62305057001SJeeja KP 	case SNDRV_PCM_TRIGGER_STOP:
62405057001SJeeja KP 		snd_hdac_ext_link_stream_clear(link_dev);
625920982c9SJeeja KP 		if (cmd == SNDRV_PCM_TRIGGER_SUSPEND)
62676f56faeSRakesh Ughreja 			snd_hdac_ext_stream_decouple(bus, stream, false);
62705057001SJeeja KP 		break;
62805057001SJeeja KP 
62905057001SJeeja KP 	default:
63005057001SJeeja KP 		return -EINVAL;
63105057001SJeeja KP 	}
63205057001SJeeja KP 	return 0;
63305057001SJeeja KP }
63405057001SJeeja KP 
63505057001SJeeja KP static int skl_link_hw_free(struct snd_pcm_substream *substream,
63605057001SJeeja KP 		struct snd_soc_dai *dai)
63705057001SJeeja KP {
63876f56faeSRakesh Ughreja 	struct hdac_bus *bus = dev_get_drvdata(dai->dev);
63905057001SJeeja KP 	struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
64005057001SJeeja KP 	struct hdac_ext_stream *link_dev =
64105057001SJeeja KP 				snd_soc_dai_get_dma_data(dai, substream);
64205057001SJeeja KP 	struct hdac_ext_link *link;
643c899df3eSRander Wang 	unsigned char stream_tag;
64405057001SJeeja KP 
64505057001SJeeja KP 	dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
64605057001SJeeja KP 
64705057001SJeeja KP 	link_dev->link_prepared = 0;
64805057001SJeeja KP 
64976f56faeSRakesh Ughreja 	link = snd_hdac_ext_bus_get_link(bus, rtd->codec_dai->component->name);
65005057001SJeeja KP 	if (!link)
65105057001SJeeja KP 		return -EINVAL;
65205057001SJeeja KP 
653c899df3eSRander Wang 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
654c899df3eSRander Wang 		stream_tag = hdac_stream(link_dev)->stream_tag;
655c899df3eSRander Wang 		snd_hdac_ext_link_clear_stream_id(link, stream_tag);
656c899df3eSRander Wang 	}
657c899df3eSRander Wang 
65805057001SJeeja KP 	snd_hdac_ext_stream_release(link_dev, HDAC_EXT_STREAM_TYPE_LINK);
65905057001SJeeja KP 	return 0;
66005057001SJeeja KP }
66105057001SJeeja KP 
66282e2b1e0SGustavo A. R. Silva static const struct snd_soc_dai_ops skl_pcm_dai_ops = {
663a40e693cSJeeja KP 	.startup = skl_pcm_open,
664a40e693cSJeeja KP 	.shutdown = skl_pcm_close,
665a40e693cSJeeja KP 	.prepare = skl_pcm_prepare,
666a40e693cSJeeja KP 	.hw_params = skl_pcm_hw_params,
667a40e693cSJeeja KP 	.hw_free = skl_pcm_hw_free,
668b663a8c5SJeeja KP 	.trigger = skl_pcm_trigger,
669a40e693cSJeeja KP };
670a40e693cSJeeja KP 
67182e2b1e0SGustavo A. R. Silva static const struct snd_soc_dai_ops skl_dmic_dai_ops = {
672b663a8c5SJeeja KP 	.hw_params = skl_be_hw_params,
673b663a8c5SJeeja KP };
674b663a8c5SJeeja KP 
67582e2b1e0SGustavo A. R. Silva static const struct snd_soc_dai_ops skl_be_ssp_dai_ops = {
676b663a8c5SJeeja KP 	.hw_params = skl_be_hw_params,
67705057001SJeeja KP };
67805057001SJeeja KP 
67982e2b1e0SGustavo A. R. Silva static const struct snd_soc_dai_ops skl_link_dai_ops = {
68005057001SJeeja KP 	.prepare = skl_link_pcm_prepare,
68105057001SJeeja KP 	.hw_params = skl_link_hw_params,
68205057001SJeeja KP 	.hw_free = skl_link_hw_free,
68305057001SJeeja KP 	.trigger = skl_link_pcm_trigger,
68405057001SJeeja KP };
68505057001SJeeja KP 
686c3ae22e3SGuneshwor Singh static struct snd_soc_dai_driver skl_fe_dai[] = {
687a40e693cSJeeja KP {
688a40e693cSJeeja KP 	.name = "System Pin",
689a40e693cSJeeja KP 	.ops = &skl_pcm_dai_ops,
690a40e693cSJeeja KP 	.playback = {
691a40e693cSJeeja KP 		.stream_name = "System Playback",
692a40e693cSJeeja KP 		.channels_min = HDA_MONO,
693a40e693cSJeeja KP 		.channels_max = HDA_STEREO,
694a40e693cSJeeja KP 		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_8000,
695dde53bccSSamaga Krishna 		.formats = SNDRV_PCM_FMTBIT_S16_LE |
696dde53bccSSamaga Krishna 			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE,
6977f975a38SJeeja KP 		.sig_bits = 32,
698a40e693cSJeeja KP 	},
699a40e693cSJeeja KP 	.capture = {
700a40e693cSJeeja KP 		.stream_name = "System Capture",
701a40e693cSJeeja KP 		.channels_min = HDA_MONO,
702a40e693cSJeeja KP 		.channels_max = HDA_STEREO,
703a40e693cSJeeja KP 		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000,
704a40e693cSJeeja KP 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
7057f975a38SJeeja KP 		.sig_bits = 32,
706a40e693cSJeeja KP 	},
707a40e693cSJeeja KP },
708a40e693cSJeeja KP {
709da3cbb40SNaveen Manohar 	.name = "System Pin2",
710da3cbb40SNaveen Manohar 	.ops = &skl_pcm_dai_ops,
711da3cbb40SNaveen Manohar 	.playback = {
712da3cbb40SNaveen Manohar 		.stream_name = "Headset Playback",
713da3cbb40SNaveen Manohar 		.channels_min = HDA_MONO,
714da3cbb40SNaveen Manohar 		.channels_max = HDA_STEREO,
715da3cbb40SNaveen Manohar 		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000 |
716da3cbb40SNaveen Manohar 			SNDRV_PCM_RATE_8000,
717da3cbb40SNaveen Manohar 		.formats = SNDRV_PCM_FMTBIT_S16_LE |
718da3cbb40SNaveen Manohar 			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE,
719da3cbb40SNaveen Manohar 	},
720da3cbb40SNaveen Manohar },
721da3cbb40SNaveen Manohar {
722da3cbb40SNaveen Manohar 	.name = "Echoref Pin",
723da3cbb40SNaveen Manohar 	.ops = &skl_pcm_dai_ops,
724da3cbb40SNaveen Manohar 	.capture = {
725da3cbb40SNaveen Manohar 		.stream_name = "Echoreference Capture",
726da3cbb40SNaveen Manohar 		.channels_min = HDA_STEREO,
727da3cbb40SNaveen Manohar 		.channels_max = HDA_STEREO,
728da3cbb40SNaveen Manohar 		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000 |
729da3cbb40SNaveen Manohar 			SNDRV_PCM_RATE_8000,
730da3cbb40SNaveen Manohar 		.formats = SNDRV_PCM_FMTBIT_S16_LE |
731da3cbb40SNaveen Manohar 			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE,
732da3cbb40SNaveen Manohar 	},
733da3cbb40SNaveen Manohar },
734da3cbb40SNaveen Manohar {
73505057001SJeeja KP 	.name = "Reference Pin",
73605057001SJeeja KP 	.ops = &skl_pcm_dai_ops,
73705057001SJeeja KP 	.capture = {
73805057001SJeeja KP 		.stream_name = "Reference Capture",
73905057001SJeeja KP 		.channels_min = HDA_MONO,
7408f35bf3fSJeeja KP 		.channels_max = HDA_QUAD,
74105057001SJeeja KP 		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000,
74205057001SJeeja KP 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
7437f975a38SJeeja KP 		.sig_bits = 32,
74405057001SJeeja KP 	},
74505057001SJeeja KP },
74605057001SJeeja KP {
747a40e693cSJeeja KP 	.name = "Deepbuffer Pin",
748a40e693cSJeeja KP 	.ops = &skl_pcm_dai_ops,
749a40e693cSJeeja KP 	.playback = {
750a40e693cSJeeja KP 		.stream_name = "Deepbuffer Playback",
751a40e693cSJeeja KP 		.channels_min = HDA_STEREO,
752a40e693cSJeeja KP 		.channels_max = HDA_STEREO,
753a40e693cSJeeja KP 		.rates = SNDRV_PCM_RATE_48000,
754a40e693cSJeeja KP 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
7557f975a38SJeeja KP 		.sig_bits = 32,
756a40e693cSJeeja KP 	},
757a40e693cSJeeja KP },
758a40e693cSJeeja KP {
759a40e693cSJeeja KP 	.name = "LowLatency Pin",
760a40e693cSJeeja KP 	.ops = &skl_pcm_dai_ops,
761a40e693cSJeeja KP 	.playback = {
762a40e693cSJeeja KP 		.stream_name = "Low Latency Playback",
763a40e693cSJeeja KP 		.channels_min = HDA_STEREO,
764a40e693cSJeeja KP 		.channels_max = HDA_STEREO,
765a40e693cSJeeja KP 		.rates = SNDRV_PCM_RATE_48000,
766a40e693cSJeeja KP 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
7677f975a38SJeeja KP 		.sig_bits = 32,
768a40e693cSJeeja KP 	},
769a40e693cSJeeja KP },
7708f35bf3fSJeeja KP {
7718f35bf3fSJeeja KP 	.name = "DMIC Pin",
7728f35bf3fSJeeja KP 	.ops = &skl_pcm_dai_ops,
7738f35bf3fSJeeja KP 	.capture = {
7748f35bf3fSJeeja KP 		.stream_name = "DMIC Capture",
7758f35bf3fSJeeja KP 		.channels_min = HDA_MONO,
7768f35bf3fSJeeja KP 		.channels_max = HDA_QUAD,
7778f35bf3fSJeeja KP 		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000,
7788f35bf3fSJeeja KP 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
7797f975a38SJeeja KP 		.sig_bits = 32,
7808f35bf3fSJeeja KP 	},
7818f35bf3fSJeeja KP },
7828cca87c0SSubhransu S. Prusty {
7838cca87c0SSubhransu S. Prusty 	.name = "HDMI1 Pin",
7848cca87c0SSubhransu S. Prusty 	.ops = &skl_pcm_dai_ops,
7858cca87c0SSubhransu S. Prusty 	.playback = {
7868cca87c0SSubhransu S. Prusty 		.stream_name = "HDMI1 Playback",
7878cca87c0SSubhransu S. Prusty 		.channels_min = HDA_STEREO,
7887e12dc87SSubhransu S. Prusty 		.channels_max = 8,
7898cca87c0SSubhransu S. Prusty 		.rates = SNDRV_PCM_RATE_32000 |	SNDRV_PCM_RATE_44100 |
7908cca87c0SSubhransu S. Prusty 			SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |
7918cca87c0SSubhransu S. Prusty 			SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |
7928cca87c0SSubhransu S. Prusty 			SNDRV_PCM_RATE_192000,
7938cca87c0SSubhransu S. Prusty 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
7948cca87c0SSubhransu S. Prusty 			SNDRV_PCM_FMTBIT_S32_LE,
7957f975a38SJeeja KP 		.sig_bits = 32,
7968cca87c0SSubhransu S. Prusty 	},
7978cca87c0SSubhransu S. Prusty },
7988cca87c0SSubhransu S. Prusty {
7998cca87c0SSubhransu S. Prusty 	.name = "HDMI2 Pin",
8008cca87c0SSubhransu S. Prusty 	.ops = &skl_pcm_dai_ops,
8018cca87c0SSubhransu S. Prusty 	.playback = {
8028cca87c0SSubhransu S. Prusty 		.stream_name = "HDMI2 Playback",
8038cca87c0SSubhransu S. Prusty 		.channels_min = HDA_STEREO,
8047e12dc87SSubhransu S. Prusty 		.channels_max = 8,
8058cca87c0SSubhransu S. Prusty 		.rates = SNDRV_PCM_RATE_32000 |	SNDRV_PCM_RATE_44100 |
8068cca87c0SSubhransu S. Prusty 			SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |
8078cca87c0SSubhransu S. Prusty 			SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |
8088cca87c0SSubhransu S. Prusty 			SNDRV_PCM_RATE_192000,
8098cca87c0SSubhransu S. Prusty 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
8108cca87c0SSubhransu S. Prusty 			SNDRV_PCM_FMTBIT_S32_LE,
8117f975a38SJeeja KP 		.sig_bits = 32,
8128cca87c0SSubhransu S. Prusty 	},
8138cca87c0SSubhransu S. Prusty },
8148cca87c0SSubhransu S. Prusty {
8158cca87c0SSubhransu S. Prusty 	.name = "HDMI3 Pin",
8168cca87c0SSubhransu S. Prusty 	.ops = &skl_pcm_dai_ops,
8178cca87c0SSubhransu S. Prusty 	.playback = {
8188cca87c0SSubhransu S. Prusty 		.stream_name = "HDMI3 Playback",
8198cca87c0SSubhransu S. Prusty 		.channels_min = HDA_STEREO,
8207e12dc87SSubhransu S. Prusty 		.channels_max = 8,
8218cca87c0SSubhransu S. Prusty 		.rates = SNDRV_PCM_RATE_32000 |	SNDRV_PCM_RATE_44100 |
8228cca87c0SSubhransu S. Prusty 			SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |
8238cca87c0SSubhransu S. Prusty 			SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |
8248cca87c0SSubhransu S. Prusty 			SNDRV_PCM_RATE_192000,
8258cca87c0SSubhransu S. Prusty 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
8268cca87c0SSubhransu S. Prusty 			SNDRV_PCM_FMTBIT_S32_LE,
8277f975a38SJeeja KP 		.sig_bits = 32,
8288cca87c0SSubhransu S. Prusty 	},
8298cca87c0SSubhransu S. Prusty },
830c3ae22e3SGuneshwor Singh };
8318f35bf3fSJeeja KP 
83205057001SJeeja KP /* BE CPU  Dais */
833c3ae22e3SGuneshwor Singh static struct snd_soc_dai_driver skl_platform_dai[] = {
83405057001SJeeja KP {
835b663a8c5SJeeja KP 	.name = "SSP0 Pin",
836b663a8c5SJeeja KP 	.ops = &skl_be_ssp_dai_ops,
837b663a8c5SJeeja KP 	.playback = {
838b663a8c5SJeeja KP 		.stream_name = "ssp0 Tx",
839b663a8c5SJeeja KP 		.channels_min = HDA_STEREO,
840b663a8c5SJeeja KP 		.channels_max = HDA_STEREO,
841b663a8c5SJeeja KP 		.rates = SNDRV_PCM_RATE_48000,
842b663a8c5SJeeja KP 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
843b663a8c5SJeeja KP 	},
844b663a8c5SJeeja KP 	.capture = {
845b663a8c5SJeeja KP 		.stream_name = "ssp0 Rx",
846b663a8c5SJeeja KP 		.channels_min = HDA_STEREO,
847b663a8c5SJeeja KP 		.channels_max = HDA_STEREO,
848b663a8c5SJeeja KP 		.rates = SNDRV_PCM_RATE_48000,
849b663a8c5SJeeja KP 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
850b663a8c5SJeeja KP 	},
851b663a8c5SJeeja KP },
852b663a8c5SJeeja KP {
853c80fd4daSJeeja KP 	.name = "SSP1 Pin",
854c80fd4daSJeeja KP 	.ops = &skl_be_ssp_dai_ops,
855c80fd4daSJeeja KP 	.playback = {
856c80fd4daSJeeja KP 		.stream_name = "ssp1 Tx",
857c80fd4daSJeeja KP 		.channels_min = HDA_STEREO,
858c80fd4daSJeeja KP 		.channels_max = HDA_STEREO,
859c80fd4daSJeeja KP 		.rates = SNDRV_PCM_RATE_48000,
860c80fd4daSJeeja KP 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
861c80fd4daSJeeja KP 	},
862c80fd4daSJeeja KP 	.capture = {
863c80fd4daSJeeja KP 		.stream_name = "ssp1 Rx",
864c80fd4daSJeeja KP 		.channels_min = HDA_STEREO,
865c80fd4daSJeeja KP 		.channels_max = HDA_STEREO,
866c80fd4daSJeeja KP 		.rates = SNDRV_PCM_RATE_48000,
867c80fd4daSJeeja KP 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
868c80fd4daSJeeja KP 	},
869c80fd4daSJeeja KP },
870c80fd4daSJeeja KP {
871fcc494afSPardha Saradhi K 	.name = "SSP2 Pin",
872fcc494afSPardha Saradhi K 	.ops = &skl_be_ssp_dai_ops,
873fcc494afSPardha Saradhi K 	.playback = {
874fcc494afSPardha Saradhi K 		.stream_name = "ssp2 Tx",
875fcc494afSPardha Saradhi K 		.channels_min = HDA_STEREO,
876fcc494afSPardha Saradhi K 		.channels_max = HDA_STEREO,
877fcc494afSPardha Saradhi K 		.rates = SNDRV_PCM_RATE_48000,
878fcc494afSPardha Saradhi K 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
879fcc494afSPardha Saradhi K 	},
880fcc494afSPardha Saradhi K 	.capture = {
881fcc494afSPardha Saradhi K 		.stream_name = "ssp2 Rx",
882fcc494afSPardha Saradhi K 		.channels_min = HDA_STEREO,
883fcc494afSPardha Saradhi K 		.channels_max = HDA_STEREO,
884fcc494afSPardha Saradhi K 		.rates = SNDRV_PCM_RATE_48000,
885fcc494afSPardha Saradhi K 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
886fcc494afSPardha Saradhi K 	},
887fcc494afSPardha Saradhi K },
888fcc494afSPardha Saradhi K {
889fcc494afSPardha Saradhi K 	.name = "SSP3 Pin",
890fcc494afSPardha Saradhi K 	.ops = &skl_be_ssp_dai_ops,
891fcc494afSPardha Saradhi K 	.playback = {
892fcc494afSPardha Saradhi K 		.stream_name = "ssp3 Tx",
893fcc494afSPardha Saradhi K 		.channels_min = HDA_STEREO,
894fcc494afSPardha Saradhi K 		.channels_max = HDA_STEREO,
895fcc494afSPardha Saradhi K 		.rates = SNDRV_PCM_RATE_48000,
896fcc494afSPardha Saradhi K 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
897fcc494afSPardha Saradhi K 	},
898fcc494afSPardha Saradhi K 	.capture = {
899fcc494afSPardha Saradhi K 		.stream_name = "ssp3 Rx",
900fcc494afSPardha Saradhi K 		.channels_min = HDA_STEREO,
901fcc494afSPardha Saradhi K 		.channels_max = HDA_STEREO,
902fcc494afSPardha Saradhi K 		.rates = SNDRV_PCM_RATE_48000,
903fcc494afSPardha Saradhi K 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
904fcc494afSPardha Saradhi K 	},
905fcc494afSPardha Saradhi K },
906fcc494afSPardha Saradhi K {
907fcc494afSPardha Saradhi K 	.name = "SSP4 Pin",
908fcc494afSPardha Saradhi K 	.ops = &skl_be_ssp_dai_ops,
909fcc494afSPardha Saradhi K 	.playback = {
910fcc494afSPardha Saradhi K 		.stream_name = "ssp4 Tx",
911fcc494afSPardha Saradhi K 		.channels_min = HDA_STEREO,
912fcc494afSPardha Saradhi K 		.channels_max = HDA_STEREO,
913fcc494afSPardha Saradhi K 		.rates = SNDRV_PCM_RATE_48000,
914fcc494afSPardha Saradhi K 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
915fcc494afSPardha Saradhi K 	},
916fcc494afSPardha Saradhi K 	.capture = {
917fcc494afSPardha Saradhi K 		.stream_name = "ssp4 Rx",
918fcc494afSPardha Saradhi K 		.channels_min = HDA_STEREO,
919fcc494afSPardha Saradhi K 		.channels_max = HDA_STEREO,
920fcc494afSPardha Saradhi K 		.rates = SNDRV_PCM_RATE_48000,
921fcc494afSPardha Saradhi K 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
922fcc494afSPardha Saradhi K 	},
923fcc494afSPardha Saradhi K },
924fcc494afSPardha Saradhi K {
925fcc494afSPardha Saradhi K 	.name = "SSP5 Pin",
926fcc494afSPardha Saradhi K 	.ops = &skl_be_ssp_dai_ops,
927fcc494afSPardha Saradhi K 	.playback = {
928fcc494afSPardha Saradhi K 		.stream_name = "ssp5 Tx",
929fcc494afSPardha Saradhi K 		.channels_min = HDA_STEREO,
930fcc494afSPardha Saradhi K 		.channels_max = HDA_STEREO,
931fcc494afSPardha Saradhi K 		.rates = SNDRV_PCM_RATE_48000,
932fcc494afSPardha Saradhi K 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
933fcc494afSPardha Saradhi K 	},
934fcc494afSPardha Saradhi K 	.capture = {
935fcc494afSPardha Saradhi K 		.stream_name = "ssp5 Rx",
936fcc494afSPardha Saradhi K 		.channels_min = HDA_STEREO,
937fcc494afSPardha Saradhi K 		.channels_max = HDA_STEREO,
938fcc494afSPardha Saradhi K 		.rates = SNDRV_PCM_RATE_48000,
939fcc494afSPardha Saradhi K 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
940fcc494afSPardha Saradhi K 	},
941fcc494afSPardha Saradhi K },
942fcc494afSPardha Saradhi K {
9438cca87c0SSubhransu S. Prusty 	.name = "iDisp1 Pin",
94405057001SJeeja KP 	.ops = &skl_link_dai_ops,
94505057001SJeeja KP 	.playback = {
9468cca87c0SSubhransu S. Prusty 		.stream_name = "iDisp1 Tx",
94705057001SJeeja KP 		.channels_min = HDA_STEREO,
9487e12dc87SSubhransu S. Prusty 		.channels_max = 8,
94905057001SJeeja KP 		.rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|SNDRV_PCM_RATE_48000,
9508cca87c0SSubhransu S. Prusty 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE |
9518cca87c0SSubhransu S. Prusty 			SNDRV_PCM_FMTBIT_S24_LE,
9528cca87c0SSubhransu S. Prusty 	},
9538cca87c0SSubhransu S. Prusty },
9548cca87c0SSubhransu S. Prusty {
9558cca87c0SSubhransu S. Prusty 	.name = "iDisp2 Pin",
9568cca87c0SSubhransu S. Prusty 	.ops = &skl_link_dai_ops,
9578cca87c0SSubhransu S. Prusty 	.playback = {
9588cca87c0SSubhransu S. Prusty 		.stream_name = "iDisp2 Tx",
9598cca87c0SSubhransu S. Prusty 		.channels_min = HDA_STEREO,
9607e12dc87SSubhransu S. Prusty 		.channels_max = 8,
9618cca87c0SSubhransu S. Prusty 		.rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|
9628cca87c0SSubhransu S. Prusty 			SNDRV_PCM_RATE_48000,
9638cca87c0SSubhransu S. Prusty 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE |
9648cca87c0SSubhransu S. Prusty 			SNDRV_PCM_FMTBIT_S24_LE,
9658cca87c0SSubhransu S. Prusty 	},
9668cca87c0SSubhransu S. Prusty },
9678cca87c0SSubhransu S. Prusty {
9688cca87c0SSubhransu S. Prusty 	.name = "iDisp3 Pin",
9698cca87c0SSubhransu S. Prusty 	.ops = &skl_link_dai_ops,
9708cca87c0SSubhransu S. Prusty 	.playback = {
9718cca87c0SSubhransu S. Prusty 		.stream_name = "iDisp3 Tx",
9728cca87c0SSubhransu S. Prusty 		.channels_min = HDA_STEREO,
9737e12dc87SSubhransu S. Prusty 		.channels_max = 8,
9748cca87c0SSubhransu S. Prusty 		.rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|
9758cca87c0SSubhransu S. Prusty 			SNDRV_PCM_RATE_48000,
9768cca87c0SSubhransu S. Prusty 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE |
9778cca87c0SSubhransu S. Prusty 			SNDRV_PCM_FMTBIT_S24_LE,
97805057001SJeeja KP 	},
97905057001SJeeja KP },
98005057001SJeeja KP {
98105057001SJeeja KP 	.name = "DMIC01 Pin",
98205057001SJeeja KP 	.ops = &skl_dmic_dai_ops,
98305057001SJeeja KP 	.capture = {
98405057001SJeeja KP 		.stream_name = "DMIC01 Rx",
9858f35bf3fSJeeja KP 		.channels_min = HDA_MONO,
9868f35bf3fSJeeja KP 		.channels_max = HDA_QUAD,
98705057001SJeeja KP 		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000,
98805057001SJeeja KP 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
98905057001SJeeja KP 	},
99005057001SJeeja KP },
99105057001SJeeja KP {
99266b48606SPawse, GuruprasadX 	.name = "DMIC16k Pin",
99366b48606SPawse, GuruprasadX 	.ops = &skl_dmic_dai_ops,
99466b48606SPawse, GuruprasadX 	.capture = {
99566b48606SPawse, GuruprasadX 		.stream_name = "DMIC16k Rx",
99666b48606SPawse, GuruprasadX 		.channels_min = HDA_MONO,
99766b48606SPawse, GuruprasadX 		.channels_max = HDA_QUAD,
99866b48606SPawse, GuruprasadX 		.rates = SNDRV_PCM_RATE_16000,
99966b48606SPawse, GuruprasadX 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
100066b48606SPawse, GuruprasadX 	},
100166b48606SPawse, GuruprasadX },
100266b48606SPawse, GuruprasadX {
10033d178713SRakesh Ughreja 	.name = "Analog CPU DAI",
100405057001SJeeja KP 	.ops = &skl_link_dai_ops,
100505057001SJeeja KP 	.playback = {
10063d178713SRakesh Ughreja 		.stream_name = "Analog CPU Playback",
10073d178713SRakesh Ughreja 		.channels_min = HDA_MONO,
10083d178713SRakesh Ughreja 		.channels_max = HDA_MAX,
10093d178713SRakesh Ughreja 		.rates = SNDRV_PCM_RATE_8000_192000,
10103d178713SRakesh Ughreja 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
10113d178713SRakesh Ughreja 			SNDRV_PCM_FMTBIT_S32_LE,
101205057001SJeeja KP 	},
101305057001SJeeja KP 	.capture = {
10143d178713SRakesh Ughreja 		.stream_name = "Analog CPU Capture",
10153d178713SRakesh Ughreja 		.channels_min = HDA_MONO,
10163d178713SRakesh Ughreja 		.channels_max = HDA_MAX,
10173d178713SRakesh Ughreja 		.rates = SNDRV_PCM_RATE_8000_192000,
10183d178713SRakesh Ughreja 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
10193d178713SRakesh Ughreja 			SNDRV_PCM_FMTBIT_S32_LE,
10203d178713SRakesh Ughreja 	},
10213d178713SRakesh Ughreja },
10223d178713SRakesh Ughreja {
10233d178713SRakesh Ughreja 	.name = "Alt Analog CPU DAI",
10243d178713SRakesh Ughreja 	.ops = &skl_link_dai_ops,
10253d178713SRakesh Ughreja 	.playback = {
10263d178713SRakesh Ughreja 		.stream_name = "Alt Analog CPU Playback",
10273d178713SRakesh Ughreja 		.channels_min = HDA_MONO,
10283d178713SRakesh Ughreja 		.channels_max = HDA_MAX,
10293d178713SRakesh Ughreja 		.rates = SNDRV_PCM_RATE_8000_192000,
10303d178713SRakesh Ughreja 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
10313d178713SRakesh Ughreja 			SNDRV_PCM_FMTBIT_S32_LE,
10323d178713SRakesh Ughreja 	},
10333d178713SRakesh Ughreja 	.capture = {
10343d178713SRakesh Ughreja 		.stream_name = "Alt Analog CPU Capture",
10353d178713SRakesh Ughreja 		.channels_min = HDA_MONO,
10363d178713SRakesh Ughreja 		.channels_max = HDA_MAX,
10373d178713SRakesh Ughreja 		.rates = SNDRV_PCM_RATE_8000_192000,
10383d178713SRakesh Ughreja 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
10393d178713SRakesh Ughreja 			SNDRV_PCM_FMTBIT_S32_LE,
10403d178713SRakesh Ughreja 	},
10413d178713SRakesh Ughreja },
10423d178713SRakesh Ughreja {
10433d178713SRakesh Ughreja 	.name = "Digital CPU DAI",
10443d178713SRakesh Ughreja 	.ops = &skl_link_dai_ops,
10453d178713SRakesh Ughreja 	.playback = {
10463d178713SRakesh Ughreja 		.stream_name = "Digital CPU Playback",
10473d178713SRakesh Ughreja 		.channels_min = HDA_MONO,
10483d178713SRakesh Ughreja 		.channels_max = HDA_MAX,
10493d178713SRakesh Ughreja 		.rates = SNDRV_PCM_RATE_8000_192000,
10503d178713SRakesh Ughreja 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
10513d178713SRakesh Ughreja 			SNDRV_PCM_FMTBIT_S32_LE,
10523d178713SRakesh Ughreja 	},
10533d178713SRakesh Ughreja 	.capture = {
10543d178713SRakesh Ughreja 		.stream_name = "Digital CPU Capture",
10553d178713SRakesh Ughreja 		.channels_min = HDA_MONO,
10563d178713SRakesh Ughreja 		.channels_max = HDA_MAX,
10573d178713SRakesh Ughreja 		.rates = SNDRV_PCM_RATE_8000_192000,
10583d178713SRakesh Ughreja 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
10593d178713SRakesh Ughreja 			SNDRV_PCM_FMTBIT_S32_LE,
106005057001SJeeja KP 	},
106105057001SJeeja KP },
1062a40e693cSJeeja KP };
1063a40e693cSJeeja KP 
1064c60b613aSLiam Girdwood int skl_dai_load(struct snd_soc_component *cmp, int index,
1065c60b613aSLiam Girdwood 			struct snd_soc_dai_driver *dai_drv,
1066c60b613aSLiam Girdwood 			struct snd_soc_tplg_pcm *pcm, struct snd_soc_dai *dai)
1067606e21fdSGuneshwor Singh {
1068c60b613aSLiam Girdwood 	dai_drv->ops = &skl_pcm_dai_ops;
1069606e21fdSGuneshwor Singh 
1070606e21fdSGuneshwor Singh 	return 0;
1071606e21fdSGuneshwor Singh }
1072606e21fdSGuneshwor Singh 
1073a40e693cSJeeja KP static int skl_platform_open(struct snd_pcm_substream *substream)
1074a40e693cSJeeja KP {
1075a40e693cSJeeja KP 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
1076a40e693cSJeeja KP 	struct snd_soc_dai_link *dai_link = rtd->dai_link;
1077a40e693cSJeeja KP 
1078a40e693cSJeeja KP 	dev_dbg(rtd->cpu_dai->dev, "In %s:%s\n", __func__,
1079a40e693cSJeeja KP 					dai_link->cpu_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 
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)
1140a40e693cSJeeja KP 			snd_hdac_stream_start(hdac_stream(stream), true);
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 
115905057001SJeeja KP static int skl_platform_pcm_trigger(struct snd_pcm_substream *substream,
116005057001SJeeja KP 					int cmd)
116105057001SJeeja KP {
116276f56faeSRakesh Ughreja 	struct hdac_bus *bus = get_bus_ctx(substream);
116305057001SJeeja KP 
116476f56faeSRakesh Ughreja 	if (!bus->ppcap)
1165b663a8c5SJeeja KP 		return skl_coupled_trigger(substream, cmd);
1166d1730c3dSJeeja KP 
1167d1730c3dSJeeja KP 	return 0;
116805057001SJeeja KP }
116905057001SJeeja KP 
11707b96144dSJeeja KP static snd_pcm_uframes_t skl_platform_pcm_pointer
11717b96144dSJeeja KP 			(struct snd_pcm_substream *substream)
1172a40e693cSJeeja KP {
11737b96144dSJeeja KP 	struct hdac_ext_stream *hstream = get_hdac_ext_stream(substream);
117476f56faeSRakesh Ughreja 	struct hdac_bus *bus = get_bus_ctx(substream);
1175a40e693cSJeeja KP 	unsigned int pos;
1176a40e693cSJeeja KP 
1177ca590c1cSDharageswari R 	/*
1178ca590c1cSDharageswari R 	 * Use DPIB for Playback stream as the periodic DMA Position-in-
1179ca590c1cSDharageswari R 	 * Buffer Writes may be scheduled at the same time or later than
1180ca590c1cSDharageswari R 	 * the MSI and does not guarantee to reflect the Position of the
1181ca590c1cSDharageswari R 	 * last buffer that was transferred. Whereas DPIB register in
1182ca590c1cSDharageswari R 	 * HAD space reflects the actual data that is transferred.
1183ca590c1cSDharageswari R 	 * Use the position buffer for capture, as DPIB write gets
1184ca590c1cSDharageswari R 	 * completed earlier than the actual data written to the DDR.
1185fdd85a05SHardik T Shah 	 *
1186fdd85a05SHardik T Shah 	 * For capture stream following workaround is required to fix the
1187fdd85a05SHardik T Shah 	 * incorrect position reporting.
1188fdd85a05SHardik T Shah 	 *
1189fdd85a05SHardik T Shah 	 * 1. Wait for 20us before reading the DMA position in buffer once
1190fdd85a05SHardik T Shah 	 * the interrupt is generated for stream completion as update happens
1191fdd85a05SHardik T Shah 	 * on the HDA frame boundary i.e. 20.833uSec.
1192fdd85a05SHardik T Shah 	 * 2. Read DPIB register to flush the DMA position value. This dummy
1193fdd85a05SHardik T Shah 	 * read is required to flush DMA position value.
1194fdd85a05SHardik T Shah 	 * 3. Read the DMA Position-in-Buffer. This value now will be equal to
1195fdd85a05SHardik T Shah 	 * or greater than period boundary.
1196ca590c1cSDharageswari R 	 */
1197fdd85a05SHardik T Shah 
1198fdd85a05SHardik T Shah 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
119976f56faeSRakesh Ughreja 		pos = readl(bus->remap_addr + AZX_REG_VS_SDXDPIB_XBASE +
1200ca590c1cSDharageswari R 				(AZX_REG_VS_SDXDPIB_XINTERVAL *
1201ca590c1cSDharageswari R 				hdac_stream(hstream)->index));
1202fdd85a05SHardik T Shah 	} else {
1203fdd85a05SHardik T Shah 		udelay(20);
120476f56faeSRakesh Ughreja 		readl(bus->remap_addr +
1205fdd85a05SHardik T Shah 				AZX_REG_VS_SDXDPIB_XBASE +
1206fdd85a05SHardik T Shah 				(AZX_REG_VS_SDXDPIB_XINTERVAL *
1207fdd85a05SHardik T Shah 				 hdac_stream(hstream)->index));
1208a40e693cSJeeja KP 		pos = snd_hdac_stream_get_pos_posbuf(hdac_stream(hstream));
1209fdd85a05SHardik T Shah 	}
1210a40e693cSJeeja KP 
1211a40e693cSJeeja KP 	if (pos >= hdac_stream(hstream)->bufsize)
1212a40e693cSJeeja KP 		pos = 0;
1213a40e693cSJeeja KP 
12147b96144dSJeeja KP 	return bytes_to_frames(substream->runtime, pos);
1215a40e693cSJeeja KP }
1216a40e693cSJeeja KP 
1217a40e693cSJeeja KP static u64 skl_adjust_codec_delay(struct snd_pcm_substream *substream,
1218a40e693cSJeeja KP 				u64 nsec)
1219a40e693cSJeeja KP {
1220a40e693cSJeeja KP 	struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
1221a40e693cSJeeja KP 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
1222a40e693cSJeeja KP 	u64 codec_frames, codec_nsecs;
1223a40e693cSJeeja KP 
1224a40e693cSJeeja KP 	if (!codec_dai->driver->ops->delay)
1225a40e693cSJeeja KP 		return nsec;
1226a40e693cSJeeja KP 
1227a40e693cSJeeja KP 	codec_frames = codec_dai->driver->ops->delay(substream, codec_dai);
1228a40e693cSJeeja KP 	codec_nsecs = div_u64(codec_frames * 1000000000LL,
1229a40e693cSJeeja KP 			      substream->runtime->rate);
1230a40e693cSJeeja KP 
1231a40e693cSJeeja KP 	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
1232a40e693cSJeeja KP 		return nsec + codec_nsecs;
1233a40e693cSJeeja KP 
1234a40e693cSJeeja KP 	return (nsec > codec_nsecs) ? nsec - codec_nsecs : 0;
1235a40e693cSJeeja KP }
1236a40e693cSJeeja KP 
1237a40e693cSJeeja KP static int skl_get_time_info(struct snd_pcm_substream *substream,
1238a40e693cSJeeja KP 			struct timespec *system_ts, struct timespec *audio_ts,
1239a40e693cSJeeja KP 			struct snd_pcm_audio_tstamp_config *audio_tstamp_config,
1240a40e693cSJeeja KP 			struct snd_pcm_audio_tstamp_report *audio_tstamp_report)
1241a40e693cSJeeja KP {
1242a40e693cSJeeja KP 	struct hdac_ext_stream *sstream = get_hdac_ext_stream(substream);
1243a40e693cSJeeja KP 	struct hdac_stream *hstr = hdac_stream(sstream);
1244a40e693cSJeeja KP 	u64 nsec;
1245a40e693cSJeeja KP 
1246a40e693cSJeeja KP 	if ((substream->runtime->hw.info & SNDRV_PCM_INFO_HAS_LINK_ATIME) &&
1247a40e693cSJeeja KP 		(audio_tstamp_config->type_requested == SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK)) {
1248a40e693cSJeeja KP 
1249a40e693cSJeeja KP 		snd_pcm_gettime(substream->runtime, system_ts);
1250a40e693cSJeeja KP 
1251a40e693cSJeeja KP 		nsec = timecounter_read(&hstr->tc);
1252a40e693cSJeeja KP 		nsec = div_u64(nsec, 3); /* can be optimized */
1253a40e693cSJeeja KP 		if (audio_tstamp_config->report_delay)
1254a40e693cSJeeja KP 			nsec = skl_adjust_codec_delay(substream, nsec);
1255a40e693cSJeeja KP 
1256a40e693cSJeeja KP 		*audio_ts = ns_to_timespec(nsec);
1257a40e693cSJeeja KP 
1258a40e693cSJeeja KP 		audio_tstamp_report->actual_type = SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK;
1259a40e693cSJeeja KP 		audio_tstamp_report->accuracy_report = 1; /* rest of struct is valid */
1260a40e693cSJeeja KP 		audio_tstamp_report->accuracy = 42; /* 24MHzWallClk == 42ns resolution */
1261a40e693cSJeeja KP 
1262a40e693cSJeeja KP 	} else {
1263a40e693cSJeeja KP 		audio_tstamp_report->actual_type = SNDRV_PCM_AUDIO_TSTAMP_TYPE_DEFAULT;
1264a40e693cSJeeja KP 	}
1265a40e693cSJeeja KP 
1266a40e693cSJeeja KP 	return 0;
1267a40e693cSJeeja KP }
1268a40e693cSJeeja KP 
1269115c7254SJulia Lawall static const struct snd_pcm_ops skl_platform_ops = {
1270a40e693cSJeeja KP 	.open = skl_platform_open,
1271a40e693cSJeeja KP 	.ioctl = snd_pcm_lib_ioctl,
1272a40e693cSJeeja KP 	.trigger = skl_platform_pcm_trigger,
1273a40e693cSJeeja KP 	.pointer = skl_platform_pcm_pointer,
1274a40e693cSJeeja KP 	.get_time_info =  skl_get_time_info,
1275a40e693cSJeeja KP 	.mmap = snd_pcm_lib_default_mmap,
1276a40e693cSJeeja KP 	.page = snd_pcm_sgbuf_ops_page,
1277a40e693cSJeeja KP };
1278a40e693cSJeeja KP 
1279a40e693cSJeeja KP static void skl_pcm_free(struct snd_pcm *pcm)
1280a40e693cSJeeja KP {
1281a40e693cSJeeja KP 	snd_pcm_lib_preallocate_free_for_all(pcm);
1282a40e693cSJeeja KP }
1283a40e693cSJeeja KP 
1284a40e693cSJeeja KP #define MAX_PREALLOC_SIZE	(32 * 1024 * 1024)
1285a40e693cSJeeja KP 
1286a40e693cSJeeja KP static int skl_pcm_new(struct snd_soc_pcm_runtime *rtd)
1287a40e693cSJeeja KP {
1288a40e693cSJeeja KP 	struct snd_soc_dai *dai = rtd->cpu_dai;
128976f56faeSRakesh Ughreja 	struct hdac_bus *bus = dev_get_drvdata(dai->dev);
1290a40e693cSJeeja KP 	struct snd_pcm *pcm = rtd->pcm;
1291a40e693cSJeeja KP 	unsigned int size;
129276f56faeSRakesh Ughreja 	struct skl *skl = bus_to_skl(bus);
1293a40e693cSJeeja KP 
1294a40e693cSJeeja KP 	if (dai->driver->playback.channels_min ||
1295a40e693cSJeeja KP 		dai->driver->capture.channels_min) {
1296a40e693cSJeeja KP 		/* buffer pre-allocation */
1297a40e693cSJeeja KP 		size = CONFIG_SND_HDA_PREALLOC_SIZE * 1024;
1298a40e693cSJeeja KP 		if (size > MAX_PREALLOC_SIZE)
1299a40e693cSJeeja KP 			size = MAX_PREALLOC_SIZE;
130062961dd5STakashi Iwai 		snd_pcm_lib_preallocate_pages_for_all(pcm,
1301a40e693cSJeeja KP 						SNDRV_DMA_TYPE_DEV_SG,
1302a40e693cSJeeja KP 						snd_dma_pci_data(skl->pci),
1303a40e693cSJeeja KP 						size, MAX_PREALLOC_SIZE);
1304a40e693cSJeeja KP 	}
1305a40e693cSJeeja KP 
130662961dd5STakashi Iwai 	return 0;
1307a40e693cSJeeja KP }
1308a40e693cSJeeja KP 
1309b26199eaSJeeja KP static int skl_get_module_info(struct skl *skl, struct skl_module_cfg *mconfig)
1310b26199eaSJeeja KP {
1311b26199eaSJeeja KP 	struct skl_sst *ctx = skl->skl_sst;
131291fe0e70SJeeja KP 	struct skl_module_inst_id *pin_id;
131391fe0e70SJeeja KP 	uuid_le *uuid_mod, *uuid_tplg;
131491fe0e70SJeeja KP 	struct skl_module *skl_module;
1315b26199eaSJeeja KP 	struct uuid_module *module;
131691fe0e70SJeeja KP 	int i, ret = -EIO;
1317b26199eaSJeeja KP 
1318b26199eaSJeeja KP 	uuid_mod = (uuid_le *)mconfig->guid;
1319b26199eaSJeeja KP 
1320b26199eaSJeeja KP 	if (list_empty(&ctx->uuid_list)) {
1321b26199eaSJeeja KP 		dev_err(ctx->dev, "Module list is empty\n");
1322b26199eaSJeeja KP 		return -EIO;
1323b26199eaSJeeja KP 	}
1324b26199eaSJeeja KP 
1325b26199eaSJeeja KP 	list_for_each_entry(module, &ctx->uuid_list, list) {
1326b26199eaSJeeja KP 		if (uuid_le_cmp(*uuid_mod, module->uuid) == 0) {
1327b26199eaSJeeja KP 			mconfig->id.module_id = module->id;
1328f6fa56e2SRamesh Babu 			if (mconfig->module)
1329f6fa56e2SRamesh Babu 				mconfig->module->loadable = module->is_loadable;
133091fe0e70SJeeja KP 			ret = 0;
133191fe0e70SJeeja KP 			break;
1332b26199eaSJeeja KP 		}
1333b26199eaSJeeja KP 	}
1334b26199eaSJeeja KP 
133591fe0e70SJeeja KP 	if (ret)
133691fe0e70SJeeja KP 		return ret;
133791fe0e70SJeeja KP 
133891fe0e70SJeeja KP 	uuid_mod = &module->uuid;
133991fe0e70SJeeja KP 	ret = -EIO;
134091fe0e70SJeeja KP 	for (i = 0; i < skl->nr_modules; i++) {
134191fe0e70SJeeja KP 		skl_module = skl->modules[i];
134291fe0e70SJeeja KP 		uuid_tplg = &skl_module->uuid;
134391fe0e70SJeeja KP 		if (!uuid_le_cmp(*uuid_mod, *uuid_tplg)) {
134491fe0e70SJeeja KP 			mconfig->module = skl_module;
134591fe0e70SJeeja KP 			ret = 0;
134691fe0e70SJeeja KP 			break;
134791fe0e70SJeeja KP 		}
134891fe0e70SJeeja KP 	}
134991fe0e70SJeeja KP 	if (skl->nr_modules && ret)
135091fe0e70SJeeja KP 		return ret;
135191fe0e70SJeeja KP 
135291fe0e70SJeeja KP 	list_for_each_entry(module, &ctx->uuid_list, list) {
135391fe0e70SJeeja KP 		for (i = 0; i < MAX_IN_QUEUE; i++) {
135491fe0e70SJeeja KP 			pin_id = &mconfig->m_in_pin[i].id;
135591fe0e70SJeeja KP 			if (!uuid_le_cmp(pin_id->mod_uuid, module->uuid))
135691fe0e70SJeeja KP 				pin_id->module_id = module->id;
135791fe0e70SJeeja KP 		}
135891fe0e70SJeeja KP 
135991fe0e70SJeeja KP 		for (i = 0; i < MAX_OUT_QUEUE; i++) {
136091fe0e70SJeeja KP 			pin_id = &mconfig->m_out_pin[i].id;
136191fe0e70SJeeja KP 			if (!uuid_le_cmp(pin_id->mod_uuid, module->uuid))
136291fe0e70SJeeja KP 				pin_id->module_id = module->id;
136391fe0e70SJeeja KP 		}
136491fe0e70SJeeja KP 	}
136591fe0e70SJeeja KP 
136691fe0e70SJeeja KP 	return 0;
1367b26199eaSJeeja KP }
1368b26199eaSJeeja KP 
136964cb1d0aSVinod Koul static int skl_populate_modules(struct skl *skl)
137064cb1d0aSVinod Koul {
137164cb1d0aSVinod Koul 	struct skl_pipeline *p;
137264cb1d0aSVinod Koul 	struct skl_pipe_module *m;
137364cb1d0aSVinod Koul 	struct snd_soc_dapm_widget *w;
137464cb1d0aSVinod Koul 	struct skl_module_cfg *mconfig;
1375b26199eaSJeeja KP 	int ret = 0;
137664cb1d0aSVinod Koul 
137764cb1d0aSVinod Koul 	list_for_each_entry(p, &skl->ppl_list, node) {
137864cb1d0aSVinod Koul 		list_for_each_entry(m, &p->pipe->w_list, node) {
137964cb1d0aSVinod Koul 			w = m->w;
138064cb1d0aSVinod Koul 			mconfig = w->priv;
138164cb1d0aSVinod Koul 
1382b26199eaSJeeja KP 			ret = skl_get_module_info(skl, mconfig);
138364cb1d0aSVinod Koul 			if (ret < 0) {
138464cb1d0aSVinod Koul 				dev_err(skl->skl_sst->dev,
1385b26199eaSJeeja KP 					"query module info failed\n");
1386b26199eaSJeeja KP 				return ret;
138764cb1d0aSVinod Koul 			}
1388f7a9f772SSriram Periyasamy 
1389f7a9f772SSriram Periyasamy 			skl_tplg_add_moduleid_in_bind_params(skl, w);
139064cb1d0aSVinod Koul 		}
139164cb1d0aSVinod Koul 	}
1392b26199eaSJeeja KP 
139364cb1d0aSVinod Koul 	return ret;
139464cb1d0aSVinod Koul }
139564cb1d0aSVinod Koul 
139656b03b4cSKuninori Morimoto static int skl_platform_soc_probe(struct snd_soc_component *component)
1397b663a8c5SJeeja KP {
139876f56faeSRakesh Ughreja 	struct hdac_bus *bus = dev_get_drvdata(component->dev);
139976f56faeSRakesh Ughreja 	struct skl *skl = bus_to_skl(bus);
140078cdbbdaSVinod Koul 	const struct skl_dsp_ops *ops;
1401fe3f4442SDharageswari R 	int ret;
1402b663a8c5SJeeja KP 
140356b03b4cSKuninori Morimoto 	pm_runtime_get_sync(component->dev);
140476f56faeSRakesh Ughreja 	if (bus->ppcap) {
140556b03b4cSKuninori Morimoto 		skl->component = component;
14065cdf6c09SVinod Koul 
14075cdf6c09SVinod Koul 		/* init debugfs */
14085cdf6c09SVinod Koul 		skl->debugfs = skl_debugfs_init(skl);
14095cdf6c09SVinod Koul 
141076f56faeSRakesh Ughreja 		ret = skl_tplg_init(component, bus);
1411fe3f4442SDharageswari R 		if (ret < 0) {
141256b03b4cSKuninori Morimoto 			dev_err(component->dev, "Failed to init topology!\n");
1413fe3f4442SDharageswari R 			return ret;
1414fe3f4442SDharageswari R 		}
141578cdbbdaSVinod Koul 
141678cdbbdaSVinod Koul 		/* load the firmwares, since all is set */
141778cdbbdaSVinod Koul 		ops = skl_get_dsp_ops(skl->pci->device);
141878cdbbdaSVinod Koul 		if (!ops)
141978cdbbdaSVinod Koul 			return -EIO;
142078cdbbdaSVinod Koul 
1421d8747d30SPierre-Louis Bossart 		if (!skl->skl_sst->is_first_boot) {
142256b03b4cSKuninori Morimoto 			dev_err(component->dev, "DSP reports first boot done!!!\n");
142378cdbbdaSVinod Koul 			return -EIO;
1424fe3f4442SDharageswari R 		}
1425b663a8c5SJeeja KP 
1426fc9fdd61SSanyog Kale 		/*
1427fc9fdd61SSanyog Kale 		 * Disable dynamic clock and power gating during firmware
1428fc9fdd61SSanyog Kale 		 * and library download
1429fc9fdd61SSanyog Kale 		 */
143056b03b4cSKuninori Morimoto 		skl->skl_sst->enable_miscbdcge(component->dev, false);
1431fc9fdd61SSanyog Kale 		skl->skl_sst->clock_power_gating(component->dev, false);
1432d5cc0a1fSPardha Saradhi K 
143356b03b4cSKuninori Morimoto 		ret = ops->init_fw(component->dev, skl->skl_sst);
143456b03b4cSKuninori Morimoto 		skl->skl_sst->enable_miscbdcge(component->dev, true);
1435fc9fdd61SSanyog Kale 		skl->skl_sst->clock_power_gating(component->dev, true);
143678cdbbdaSVinod Koul 		if (ret < 0) {
143756b03b4cSKuninori Morimoto 			dev_err(component->dev, "Failed to boot first fw: %d\n", ret);
143878cdbbdaSVinod Koul 			return ret;
143978cdbbdaSVinod Koul 		}
144064cb1d0aSVinod Koul 		skl_populate_modules(skl);
1441a26a3f53SPardha Saradhi K 		skl->skl_sst->update_d0i3c = skl_update_d0i3c;
1442cb729d80SG Kranthi 		skl_dsp_enable_notification(skl->skl_sst, false);
14439452314dSPradeep Tewani 
14449452314dSPradeep Tewani 		if (skl->cfg.astate_cfg != NULL) {
14459452314dSPradeep Tewani 			skl_dsp_set_astate_cfg(skl->skl_sst,
14469452314dSPradeep Tewani 					skl->cfg.astate_cfg->count,
14479452314dSPradeep Tewani 					skl->cfg.astate_cfg);
14489452314dSPradeep Tewani 		}
144978cdbbdaSVinod Koul 	}
145056b03b4cSKuninori Morimoto 	pm_runtime_mark_last_busy(component->dev);
145156b03b4cSKuninori Morimoto 	pm_runtime_put_autosuspend(component->dev);
145278cdbbdaSVinod Koul 
1453b663a8c5SJeeja KP 	return 0;
1454b663a8c5SJeeja KP }
145556b03b4cSKuninori Morimoto 
14562e05ddd2SRanjani Sridharan static void skl_pcm_remove(struct snd_soc_component *component)
14572e05ddd2SRanjani Sridharan {
14582e05ddd2SRanjani Sridharan 	/* remove topology */
14592e05ddd2SRanjani Sridharan 	snd_soc_tplg_component_remove(component, SND_SOC_TPLG_INDEX_ALL);
14602e05ddd2SRanjani Sridharan }
14612e05ddd2SRanjani Sridharan 
146256b03b4cSKuninori Morimoto static const struct snd_soc_component_driver skl_component  = {
146356b03b4cSKuninori Morimoto 	.name		= "pcm",
1464b663a8c5SJeeja KP 	.probe		= skl_platform_soc_probe,
14652e05ddd2SRanjani Sridharan 	.remove		= skl_pcm_remove,
1466a40e693cSJeeja KP 	.ops		= &skl_platform_ops,
1467a40e693cSJeeja KP 	.pcm_new	= skl_pcm_new,
1468a40e693cSJeeja KP 	.pcm_free	= skl_pcm_free,
1469b4ed6b51SRanjani Sridharan 	.module_get_upon_open = 1, /* increment refcount when a pcm is opened */
1470a40e693cSJeeja KP };
1471a40e693cSJeeja KP 
1472a40e693cSJeeja KP int skl_platform_register(struct device *dev)
1473a40e693cSJeeja KP {
1474a40e693cSJeeja KP 	int ret;
1475c3ae22e3SGuneshwor Singh 	struct snd_soc_dai_driver *dais;
1476c3ae22e3SGuneshwor Singh 	int num_dais = ARRAY_SIZE(skl_platform_dai);
147776f56faeSRakesh Ughreja 	struct hdac_bus *bus = dev_get_drvdata(dev);
147876f56faeSRakesh Ughreja 	struct skl *skl = bus_to_skl(bus);
1479b663a8c5SJeeja KP 
1480b663a8c5SJeeja KP 	INIT_LIST_HEAD(&skl->ppl_list);
1481b8c722ddSJeeja KP 	INIT_LIST_HEAD(&skl->bind_list);
1482a40e693cSJeeja KP 
1483c3ae22e3SGuneshwor Singh 	skl->dais = kmemdup(skl_platform_dai, sizeof(skl_platform_dai),
1484c3ae22e3SGuneshwor Singh 			    GFP_KERNEL);
1485c3ae22e3SGuneshwor Singh 	if (!skl->dais) {
1486c3ae22e3SGuneshwor Singh 		ret = -ENOMEM;
1487c3ae22e3SGuneshwor Singh 		goto err;
1488a40e693cSJeeja KP 	}
1489a40e693cSJeeja KP 
1490c3ae22e3SGuneshwor Singh 	if (!skl->use_tplg_pcm) {
1491c3ae22e3SGuneshwor Singh 		dais = krealloc(skl->dais, sizeof(skl_fe_dai) +
1492c3ae22e3SGuneshwor Singh 				sizeof(skl_platform_dai), GFP_KERNEL);
1493c3ae22e3SGuneshwor Singh 		if (!dais) {
1494c3ae22e3SGuneshwor Singh 			ret = -ENOMEM;
1495c3ae22e3SGuneshwor Singh 			goto err;
1496c3ae22e3SGuneshwor Singh 		}
1497c3ae22e3SGuneshwor Singh 
1498c3ae22e3SGuneshwor Singh 		skl->dais = dais;
1499c3ae22e3SGuneshwor Singh 		memcpy(&skl->dais[ARRAY_SIZE(skl_platform_dai)], skl_fe_dai,
1500c3ae22e3SGuneshwor Singh 		       sizeof(skl_fe_dai));
1501c3ae22e3SGuneshwor Singh 		num_dais += ARRAY_SIZE(skl_fe_dai);
1502c3ae22e3SGuneshwor Singh 	}
1503c3ae22e3SGuneshwor Singh 
150456b03b4cSKuninori Morimoto 	ret = devm_snd_soc_register_component(dev, &skl_component,
1505c3ae22e3SGuneshwor Singh 					 skl->dais, num_dais);
150656b03b4cSKuninori Morimoto 	if (ret)
1507c3ae22e3SGuneshwor Singh 		dev_err(dev, "soc component registration failed %d\n", ret);
1508c3ae22e3SGuneshwor Singh err:
1509a40e693cSJeeja KP 	return ret;
1510a40e693cSJeeja KP }
1511a40e693cSJeeja KP 
1512a40e693cSJeeja KP int skl_platform_unregister(struct device *dev)
1513a40e693cSJeeja KP {
151476f56faeSRakesh Ughreja 	struct hdac_bus *bus = dev_get_drvdata(dev);
151576f56faeSRakesh Ughreja 	struct skl *skl = bus_to_skl(bus);
1516550b349aSDan Carpenter 	struct skl_module_deferred_bind *modules, *tmp;
1517b8c722ddSJeeja KP 
1518b8c722ddSJeeja KP 	if (!list_empty(&skl->bind_list)) {
1519550b349aSDan Carpenter 		list_for_each_entry_safe(modules, tmp, &skl->bind_list, node) {
1520b8c722ddSJeeja KP 			list_del(&modules->node);
1521b8c722ddSJeeja KP 			kfree(modules);
1522b8c722ddSJeeja KP 		}
1523b8c722ddSJeeja KP 	}
1524b8c722ddSJeeja KP 
1525c3ae22e3SGuneshwor Singh 	kfree(skl->dais);
1526c3ae22e3SGuneshwor Singh 
1527a40e693cSJeeja KP 	return 0;
1528a40e693cSJeeja KP }
1529