xref: /openbmc/linux/sound/soc/intel/skylake/skl-pcm.c (revision d5cc0a1f)
1a40e693cSJeeja KP /*
2a40e693cSJeeja KP  *  skl-pcm.c -ASoC HDA Platform driver file implementing PCM functionality
3a40e693cSJeeja KP  *
4a40e693cSJeeja KP  *  Copyright (C) 2014-2015 Intel Corp
5a40e693cSJeeja KP  *  Author:  Jeeja KP <jeeja.kp@intel.com>
6a40e693cSJeeja KP  *
7a40e693cSJeeja KP  *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8a40e693cSJeeja KP  *
9a40e693cSJeeja KP  *  This program is free software; you can redistribute it and/or modify
10a40e693cSJeeja KP  *  it under the terms of the GNU General Public License as published by
11a40e693cSJeeja KP  *  the Free Software Foundation; version 2 of the License.
12a40e693cSJeeja KP  *
13a40e693cSJeeja KP  *  This program is distributed in the hope that it will be useful, but
14a40e693cSJeeja KP  *  WITHOUT ANY WARRANTY; without even the implied warranty of
15a40e693cSJeeja KP  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16a40e693cSJeeja KP  *  General Public License for more details.
17a40e693cSJeeja KP  *
18a40e693cSJeeja KP  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
19a40e693cSJeeja KP  *
20a40e693cSJeeja KP  */
21a40e693cSJeeja KP 
22a40e693cSJeeja KP #include <linux/pci.h>
23a40e693cSJeeja KP #include <linux/pm_runtime.h>
24fdd85a05SHardik T Shah #include <linux/delay.h>
25a40e693cSJeeja KP #include <sound/pcm_params.h>
26a40e693cSJeeja KP #include <sound/soc.h>
27a40e693cSJeeja KP #include "skl.h"
28b663a8c5SJeeja KP #include "skl-topology.h"
29721c3e36SDharageswari.R #include "skl-sst-dsp.h"
30721c3e36SDharageswari.R #include "skl-sst-ipc.h"
31a40e693cSJeeja KP 
32a40e693cSJeeja KP #define HDA_MONO 1
33a40e693cSJeeja KP #define HDA_STEREO 2
348f35bf3fSJeeja KP #define HDA_QUAD 4
35a40e693cSJeeja KP 
368df397ffSBhumika Goyal static const struct snd_pcm_hardware azx_pcm_hw = {
37a40e693cSJeeja KP 	.info =			(SNDRV_PCM_INFO_MMAP |
38a40e693cSJeeja KP 				 SNDRV_PCM_INFO_INTERLEAVED |
39a40e693cSJeeja KP 				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
40a40e693cSJeeja KP 				 SNDRV_PCM_INFO_MMAP_VALID |
41a40e693cSJeeja KP 				 SNDRV_PCM_INFO_PAUSE |
423637976bSJeeja KP 				 SNDRV_PCM_INFO_RESUME |
43a40e693cSJeeja KP 				 SNDRV_PCM_INFO_SYNC_START |
44a40e693cSJeeja KP 				 SNDRV_PCM_INFO_HAS_WALL_CLOCK | /* legacy */
45a40e693cSJeeja KP 				 SNDRV_PCM_INFO_HAS_LINK_ATIME |
46a40e693cSJeeja KP 				 SNDRV_PCM_INFO_NO_PERIOD_WAKEUP),
4706b23d93SJeeja KP 	.formats =		SNDRV_PCM_FMTBIT_S16_LE |
4806b23d93SJeeja KP 				SNDRV_PCM_FMTBIT_S32_LE |
4906b23d93SJeeja KP 				SNDRV_PCM_FMTBIT_S24_LE,
5006b23d93SJeeja KP 	.rates =		SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000 |
5106b23d93SJeeja KP 				SNDRV_PCM_RATE_8000,
5206b23d93SJeeja KP 	.rate_min =		8000,
53a40e693cSJeeja KP 	.rate_max =		48000,
548f35bf3fSJeeja KP 	.channels_min =		1,
557e12dc87SSubhransu S. Prusty 	.channels_max =		8,
56a40e693cSJeeja KP 	.buffer_bytes_max =	AZX_MAX_BUF_SIZE,
57a40e693cSJeeja KP 	.period_bytes_min =	128,
58a40e693cSJeeja KP 	.period_bytes_max =	AZX_MAX_BUF_SIZE / 2,
59a40e693cSJeeja KP 	.periods_min =		2,
60a40e693cSJeeja KP 	.periods_max =		AZX_MAX_FRAG,
61a40e693cSJeeja KP 	.fifo_size =		0,
62a40e693cSJeeja KP };
63a40e693cSJeeja KP 
64a40e693cSJeeja KP static inline
65a40e693cSJeeja KP struct hdac_ext_stream *get_hdac_ext_stream(struct snd_pcm_substream *substream)
66a40e693cSJeeja KP {
67a40e693cSJeeja KP 	return substream->runtime->private_data;
68a40e693cSJeeja KP }
69a40e693cSJeeja KP 
70a40e693cSJeeja KP static struct hdac_ext_bus *get_bus_ctx(struct snd_pcm_substream *substream)
71a40e693cSJeeja KP {
72a40e693cSJeeja KP 	struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
73a40e693cSJeeja KP 	struct hdac_stream *hstream = hdac_stream(stream);
74a40e693cSJeeja KP 	struct hdac_bus *bus = hstream->bus;
75a40e693cSJeeja KP 
76a40e693cSJeeja KP 	return hbus_to_ebus(bus);
77a40e693cSJeeja KP }
78a40e693cSJeeja KP 
79a40e693cSJeeja KP static int skl_substream_alloc_pages(struct hdac_ext_bus *ebus,
80a40e693cSJeeja KP 				 struct snd_pcm_substream *substream,
81a40e693cSJeeja KP 				 size_t size)
82a40e693cSJeeja KP {
83a40e693cSJeeja KP 	struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
84a40e693cSJeeja KP 
85a40e693cSJeeja KP 	hdac_stream(stream)->bufsize = 0;
86a40e693cSJeeja KP 	hdac_stream(stream)->period_bytes = 0;
87a40e693cSJeeja KP 	hdac_stream(stream)->format_val = 0;
88a40e693cSJeeja KP 
89a40e693cSJeeja KP 	return snd_pcm_lib_malloc_pages(substream, size);
90a40e693cSJeeja KP }
91a40e693cSJeeja KP 
92a40e693cSJeeja KP static int skl_substream_free_pages(struct hdac_bus *bus,
93a40e693cSJeeja KP 				struct snd_pcm_substream *substream)
94a40e693cSJeeja KP {
95a40e693cSJeeja KP 	return snd_pcm_lib_free_pages(substream);
96a40e693cSJeeja KP }
97a40e693cSJeeja KP 
98a40e693cSJeeja KP static void skl_set_pcm_constrains(struct hdac_ext_bus *ebus,
99a40e693cSJeeja KP 				 struct snd_pcm_runtime *runtime)
100a40e693cSJeeja KP {
101a40e693cSJeeja KP 	snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
102a40e693cSJeeja KP 
103a40e693cSJeeja KP 	/* avoid wrap-around with wall-clock */
104a40e693cSJeeja KP 	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_TIME,
105a40e693cSJeeja KP 				     20, 178000000);
106a40e693cSJeeja KP }
107a40e693cSJeeja KP 
10805057001SJeeja KP static enum hdac_ext_stream_type skl_get_host_stream_type(struct hdac_ext_bus *ebus)
10905057001SJeeja KP {
110ec8ae570SVinod Koul 	if ((ebus_to_hbus(ebus))->ppcap)
11105057001SJeeja KP 		return HDAC_EXT_STREAM_TYPE_HOST;
11205057001SJeeja KP 	else
11305057001SJeeja KP 		return HDAC_EXT_STREAM_TYPE_COUPLED;
11405057001SJeeja KP }
11505057001SJeeja KP 
1164557c305SJeeja KP /*
1174557c305SJeeja KP  * check if the stream opened is marked as ignore_suspend by machine, if so
1184557c305SJeeja KP  * then enable suspend_active refcount
1194557c305SJeeja KP  *
1204557c305SJeeja KP  * The count supend_active does not need lock as it is used in open/close
1214557c305SJeeja KP  * and suspend context
1224557c305SJeeja KP  */
1234557c305SJeeja KP static void skl_set_suspend_active(struct snd_pcm_substream *substream,
1244557c305SJeeja KP 					 struct snd_soc_dai *dai, bool enable)
1254557c305SJeeja KP {
1264557c305SJeeja KP 	struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev);
1274557c305SJeeja KP 	struct snd_soc_dapm_widget *w;
1284557c305SJeeja KP 	struct skl *skl = ebus_to_skl(ebus);
1294557c305SJeeja KP 
1304557c305SJeeja KP 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
1314557c305SJeeja KP 		w = dai->playback_widget;
1324557c305SJeeja KP 	else
1334557c305SJeeja KP 		w = dai->capture_widget;
1344557c305SJeeja KP 
1354557c305SJeeja KP 	if (w->ignore_suspend && enable)
1364557c305SJeeja KP 		skl->supend_active++;
1374557c305SJeeja KP 	else if (w->ignore_suspend && !enable)
1384557c305SJeeja KP 		skl->supend_active--;
1394557c305SJeeja KP }
1404557c305SJeeja KP 
141ad036bdeSJeeja KP int skl_pcm_host_dma_prepare(struct device *dev, struct skl_pipe_params *params)
142ad036bdeSJeeja KP {
143ad036bdeSJeeja KP 	struct hdac_ext_bus *ebus = dev_get_drvdata(dev);
144ad036bdeSJeeja KP 	struct hdac_bus *bus = ebus_to_hbus(ebus);
145ad036bdeSJeeja KP 	unsigned int format_val;
146ad036bdeSJeeja KP 	struct hdac_stream *hstream;
147ad036bdeSJeeja KP 	struct hdac_ext_stream *stream;
148ad036bdeSJeeja KP 	int err;
149ad036bdeSJeeja KP 
150ad036bdeSJeeja KP 	hstream = snd_hdac_get_stream(bus, params->stream,
151ad036bdeSJeeja KP 					params->host_dma_id + 1);
152ad036bdeSJeeja KP 	if (!hstream)
153ad036bdeSJeeja KP 		return -EINVAL;
154ad036bdeSJeeja KP 
155ad036bdeSJeeja KP 	stream = stream_to_hdac_ext_stream(hstream);
156ad036bdeSJeeja KP 	snd_hdac_ext_stream_decouple(ebus, stream, true);
157ad036bdeSJeeja KP 
158ad036bdeSJeeja KP 	format_val = snd_hdac_calc_stream_format(params->s_freq,
1597f975a38SJeeja KP 			params->ch, params->format, params->host_bps, 0);
160ad036bdeSJeeja KP 
161ad036bdeSJeeja KP 	dev_dbg(dev, "format_val=%d, rate=%d, ch=%d, format=%d\n",
162ad036bdeSJeeja KP 		format_val, params->s_freq, params->ch, params->format);
163ad036bdeSJeeja KP 
164ad036bdeSJeeja KP 	snd_hdac_stream_reset(hdac_stream(stream));
165ad036bdeSJeeja KP 	err = snd_hdac_stream_set_params(hdac_stream(stream), format_val);
166ad036bdeSJeeja KP 	if (err < 0)
167ad036bdeSJeeja KP 		return err;
168ad036bdeSJeeja KP 
169ad036bdeSJeeja KP 	err = snd_hdac_stream_setup(hdac_stream(stream));
170ad036bdeSJeeja KP 	if (err < 0)
171ad036bdeSJeeja KP 		return err;
172ad036bdeSJeeja KP 
173ad036bdeSJeeja KP 	hdac_stream(stream)->prepared = 1;
174ad036bdeSJeeja KP 
175ad036bdeSJeeja KP 	return 0;
176ad036bdeSJeeja KP }
177ad036bdeSJeeja KP 
178ad036bdeSJeeja KP int skl_pcm_link_dma_prepare(struct device *dev, struct skl_pipe_params *params)
179ad036bdeSJeeja KP {
180ad036bdeSJeeja KP 	struct hdac_ext_bus *ebus = dev_get_drvdata(dev);
181ad036bdeSJeeja KP 	struct hdac_bus *bus = ebus_to_hbus(ebus);
182ad036bdeSJeeja KP 	unsigned int format_val;
183ad036bdeSJeeja KP 	struct hdac_stream *hstream;
184ad036bdeSJeeja KP 	struct hdac_ext_stream *stream;
185ad036bdeSJeeja KP 	struct hdac_ext_link *link;
186ad036bdeSJeeja KP 
187ad036bdeSJeeja KP 	hstream = snd_hdac_get_stream(bus, params->stream,
188ad036bdeSJeeja KP 					params->link_dma_id + 1);
189ad036bdeSJeeja KP 	if (!hstream)
190ad036bdeSJeeja KP 		return -EINVAL;
191ad036bdeSJeeja KP 
192ad036bdeSJeeja KP 	stream = stream_to_hdac_ext_stream(hstream);
193ad036bdeSJeeja KP 	snd_hdac_ext_stream_decouple(ebus, stream, true);
1947f975a38SJeeja KP 	format_val = snd_hdac_calc_stream_format(params->s_freq, params->ch,
1957f975a38SJeeja KP 					params->format, params->link_bps, 0);
196ad036bdeSJeeja KP 
197ad036bdeSJeeja KP 	dev_dbg(dev, "format_val=%d, rate=%d, ch=%d, format=%d\n",
198ad036bdeSJeeja KP 		format_val, params->s_freq, params->ch, params->format);
199ad036bdeSJeeja KP 
200ad036bdeSJeeja KP 	snd_hdac_ext_link_stream_reset(stream);
201ad036bdeSJeeja KP 
202ad036bdeSJeeja KP 	snd_hdac_ext_link_stream_setup(stream, format_val);
203ad036bdeSJeeja KP 
204ad036bdeSJeeja KP 	list_for_each_entry(link, &ebus->hlink_list, list) {
205ad036bdeSJeeja KP 		if (link->index == params->link_index)
206ad036bdeSJeeja KP 			snd_hdac_ext_link_set_stream_id(link,
207ad036bdeSJeeja KP 					hstream->stream_tag);
208ad036bdeSJeeja KP 	}
209ad036bdeSJeeja KP 
210ad036bdeSJeeja KP 	stream->link_prepared = 1;
211ad036bdeSJeeja KP 
212ad036bdeSJeeja KP 	return 0;
213ad036bdeSJeeja KP }
214ad036bdeSJeeja KP 
215a40e693cSJeeja KP static int skl_pcm_open(struct snd_pcm_substream *substream,
216a40e693cSJeeja KP 		struct snd_soc_dai *dai)
217a40e693cSJeeja KP {
218a40e693cSJeeja KP 	struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev);
219a40e693cSJeeja KP 	struct hdac_ext_stream *stream;
220a40e693cSJeeja KP 	struct snd_pcm_runtime *runtime = substream->runtime;
221a40e693cSJeeja KP 	struct skl_dma_params *dma_params;
222a83e3b4cSVinod Koul 	struct skl *skl = get_skl_ctx(dai->dev);
223a83e3b4cSVinod Koul 	struct skl_module_cfg *mconfig;
224a40e693cSJeeja KP 
225a40e693cSJeeja KP 	dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
226a40e693cSJeeja KP 
227a40e693cSJeeja KP 	stream = snd_hdac_ext_stream_assign(ebus, substream,
22805057001SJeeja KP 					skl_get_host_stream_type(ebus));
229a40e693cSJeeja KP 	if (stream == NULL)
230a40e693cSJeeja KP 		return -EBUSY;
231a40e693cSJeeja KP 
232a40e693cSJeeja KP 	skl_set_pcm_constrains(ebus, runtime);
233a40e693cSJeeja KP 
234a40e693cSJeeja KP 	/*
235a40e693cSJeeja KP 	 * disable WALLCLOCK timestamps for capture streams
236a40e693cSJeeja KP 	 * until we figure out how to handle digital inputs
237a40e693cSJeeja KP 	 */
238a40e693cSJeeja KP 	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
239a40e693cSJeeja KP 		runtime->hw.info &= ~SNDRV_PCM_INFO_HAS_WALL_CLOCK; /* legacy */
240a40e693cSJeeja KP 		runtime->hw.info &= ~SNDRV_PCM_INFO_HAS_LINK_ATIME;
241a40e693cSJeeja KP 	}
242a40e693cSJeeja KP 
243a40e693cSJeeja KP 	runtime->private_data = stream;
244a40e693cSJeeja KP 
245a40e693cSJeeja KP 	dma_params = kzalloc(sizeof(*dma_params), GFP_KERNEL);
246a40e693cSJeeja KP 	if (!dma_params)
247a40e693cSJeeja KP 		return -ENOMEM;
248a40e693cSJeeja KP 
249a40e693cSJeeja KP 	dma_params->stream_tag = hdac_stream(stream)->stream_tag;
250a40e693cSJeeja KP 	snd_soc_dai_set_dma_data(dai, substream, dma_params);
251a40e693cSJeeja KP 
252a40e693cSJeeja KP 	dev_dbg(dai->dev, "stream tag set in dma params=%d\n",
253a40e693cSJeeja KP 				 dma_params->stream_tag);
2544557c305SJeeja KP 	skl_set_suspend_active(substream, dai, true);
255a40e693cSJeeja KP 	snd_pcm_set_sync(substream);
256a40e693cSJeeja KP 
257a83e3b4cSVinod Koul 	mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream);
25891ce5497SG Kranthi 	if (!mconfig)
25991ce5497SG Kranthi 		return -EINVAL;
26091ce5497SG Kranthi 
261a83e3b4cSVinod Koul 	skl_tplg_d0i3_get(skl, mconfig->d0i3_caps);
262a83e3b4cSVinod Koul 
263a40e693cSJeeja KP 	return 0;
264a40e693cSJeeja KP }
265a40e693cSJeeja KP 
266a40e693cSJeeja KP static int skl_pcm_prepare(struct snd_pcm_substream *substream,
267a40e693cSJeeja KP 		struct snd_soc_dai *dai)
268a40e693cSJeeja KP {
2692004432fSJeeja KP 	struct skl *skl = get_skl_ctx(dai->dev);
2702004432fSJeeja KP 	struct skl_module_cfg *mconfig;
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 
2762004432fSJeeja KP 	/* In case of XRUN recovery, reset the FW pipe to clean state */
2772004432fSJeeja KP 	if (mconfig && (substream->runtime->status->state ==
2782004432fSJeeja KP 					SNDRV_PCM_STATE_XRUN))
2792004432fSJeeja KP 		skl_reset_pipe(skl->skl_sst, mconfig->pipe);
2802004432fSJeeja KP 
281bb704a73SJeeja KP 	return 0;
282a40e693cSJeeja KP }
283a40e693cSJeeja KP 
284a40e693cSJeeja KP static int skl_pcm_hw_params(struct snd_pcm_substream *substream,
285a40e693cSJeeja KP 				struct snd_pcm_hw_params *params,
286a40e693cSJeeja KP 				struct snd_soc_dai *dai)
287a40e693cSJeeja KP {
288a40e693cSJeeja KP 	struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev);
28905057001SJeeja KP 	struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
290a40e693cSJeeja KP 	struct snd_pcm_runtime *runtime = substream->runtime;
291b663a8c5SJeeja KP 	struct skl_pipe_params p_params = {0};
292b663a8c5SJeeja KP 	struct skl_module_cfg *m_cfg;
29305057001SJeeja KP 	int ret, dma_id;
294a40e693cSJeeja KP 
295a40e693cSJeeja KP 	dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
296a40e693cSJeeja KP 	ret = skl_substream_alloc_pages(ebus, substream,
297a40e693cSJeeja KP 					  params_buffer_bytes(params));
298a40e693cSJeeja KP 	if (ret < 0)
299a40e693cSJeeja KP 		return ret;
300a40e693cSJeeja KP 
301a40e693cSJeeja KP 	dev_dbg(dai->dev, "format_val, rate=%d, ch=%d, format=%d\n",
302a40e693cSJeeja KP 			runtime->rate, runtime->channels, runtime->format);
303a40e693cSJeeja KP 
30405057001SJeeja KP 	dma_id = hdac_stream(stream)->stream_tag - 1;
30505057001SJeeja KP 	dev_dbg(dai->dev, "dma_id=%d\n", dma_id);
30605057001SJeeja KP 
307b663a8c5SJeeja KP 	p_params.s_fmt = snd_pcm_format_width(params_format(params));
308b663a8c5SJeeja KP 	p_params.ch = params_channels(params);
309b663a8c5SJeeja KP 	p_params.s_freq = params_rate(params);
310b663a8c5SJeeja KP 	p_params.host_dma_id = dma_id;
311b663a8c5SJeeja KP 	p_params.stream = substream->stream;
31212c3be0eSJeeja KP 	p_params.format = params_format(params);
3137f975a38SJeeja KP 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
3147f975a38SJeeja KP 		p_params.host_bps = dai->driver->playback.sig_bits;
3157f975a38SJeeja KP 	else
3167f975a38SJeeja KP 		p_params.host_bps = dai->driver->capture.sig_bits;
3177f975a38SJeeja KP 
318b663a8c5SJeeja KP 
319b663a8c5SJeeja KP 	m_cfg = skl_tplg_fe_get_cpr_module(dai, p_params.stream);
320b663a8c5SJeeja KP 	if (m_cfg)
321b663a8c5SJeeja KP 		skl_tplg_update_pipe_params(dai->dev, m_cfg, &p_params);
322b663a8c5SJeeja KP 
323a40e693cSJeeja KP 	return 0;
324a40e693cSJeeja KP }
325a40e693cSJeeja KP 
326a40e693cSJeeja KP static void skl_pcm_close(struct snd_pcm_substream *substream,
327a40e693cSJeeja KP 		struct snd_soc_dai *dai)
328a40e693cSJeeja KP {
329a40e693cSJeeja KP 	struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
33005057001SJeeja KP 	struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev);
331a40e693cSJeeja KP 	struct skl_dma_params *dma_params = NULL;
332721c3e36SDharageswari.R 	struct skl *skl = ebus_to_skl(ebus);
333a83e3b4cSVinod Koul 	struct skl_module_cfg *mconfig;
334a40e693cSJeeja KP 
335a40e693cSJeeja KP 	dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
33605057001SJeeja KP 
33705057001SJeeja KP 	snd_hdac_ext_stream_release(stream, skl_get_host_stream_type(ebus));
338a40e693cSJeeja KP 
339a40e693cSJeeja KP 	dma_params = snd_soc_dai_get_dma_data(dai, substream);
340a40e693cSJeeja KP 	/*
341a40e693cSJeeja KP 	 * now we should set this to NULL as we are freeing by the
342a40e693cSJeeja KP 	 * dma_params
343a40e693cSJeeja KP 	 */
344a40e693cSJeeja KP 	snd_soc_dai_set_dma_data(dai, substream, NULL);
3454557c305SJeeja KP 	skl_set_suspend_active(substream, dai, false);
346a40e693cSJeeja KP 
347721c3e36SDharageswari.R 	/*
348721c3e36SDharageswari.R 	 * check if close is for "Reference Pin" and set back the
349721c3e36SDharageswari.R 	 * CGCTL.MISCBDCGE if disabled by driver
350721c3e36SDharageswari.R 	 */
351721c3e36SDharageswari.R 	if (!strncmp(dai->name, "Reference Pin", 13) &&
352721c3e36SDharageswari.R 			skl->skl_sst->miscbdcg_disabled) {
353721c3e36SDharageswari.R 		skl->skl_sst->enable_miscbdcge(dai->dev, true);
354721c3e36SDharageswari.R 		skl->skl_sst->miscbdcg_disabled = false;
355721c3e36SDharageswari.R 	}
356721c3e36SDharageswari.R 
357a83e3b4cSVinod Koul 	mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream);
358a83e3b4cSVinod Koul 	skl_tplg_d0i3_put(skl, mconfig->d0i3_caps);
359a83e3b4cSVinod Koul 
360a40e693cSJeeja KP 	kfree(dma_params);
361a40e693cSJeeja KP }
362a40e693cSJeeja KP 
363a40e693cSJeeja KP static int skl_pcm_hw_free(struct snd_pcm_substream *substream,
364a40e693cSJeeja KP 		struct snd_soc_dai *dai)
365a40e693cSJeeja KP {
366a40e693cSJeeja KP 	struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev);
367a40e693cSJeeja KP 	struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
368a40e693cSJeeja KP 
369a40e693cSJeeja KP 	dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
370a40e693cSJeeja KP 
371a40e693cSJeeja KP 	snd_hdac_stream_cleanup(hdac_stream(stream));
372a40e693cSJeeja KP 	hdac_stream(stream)->prepared = 0;
373a40e693cSJeeja KP 
374a40e693cSJeeja KP 	return skl_substream_free_pages(ebus_to_hbus(ebus), substream);
375a40e693cSJeeja KP }
376a40e693cSJeeja KP 
377b663a8c5SJeeja KP static int skl_be_hw_params(struct snd_pcm_substream *substream,
378b663a8c5SJeeja KP 				struct snd_pcm_hw_params *params,
379b663a8c5SJeeja KP 				struct snd_soc_dai *dai)
380b663a8c5SJeeja KP {
381b663a8c5SJeeja KP 	struct skl_pipe_params p_params = {0};
382b663a8c5SJeeja KP 
383b663a8c5SJeeja KP 	p_params.s_fmt = snd_pcm_format_width(params_format(params));
384b663a8c5SJeeja KP 	p_params.ch = params_channels(params);
385b663a8c5SJeeja KP 	p_params.s_freq = params_rate(params);
386b663a8c5SJeeja KP 	p_params.stream = substream->stream;
387b663a8c5SJeeja KP 
3884bd073f9SJeeja KP 	return skl_tplg_be_update_params(dai, &p_params);
389b663a8c5SJeeja KP }
390b663a8c5SJeeja KP 
391d1730c3dSJeeja KP static int skl_decoupled_trigger(struct snd_pcm_substream *substream,
392d1730c3dSJeeja KP 		int cmd)
393d1730c3dSJeeja KP {
394d1730c3dSJeeja KP 	struct hdac_ext_bus *ebus = get_bus_ctx(substream);
395d1730c3dSJeeja KP 	struct hdac_bus *bus = ebus_to_hbus(ebus);
396d1730c3dSJeeja KP 	struct hdac_ext_stream *stream;
397d1730c3dSJeeja KP 	int start;
398d1730c3dSJeeja KP 	unsigned long cookie;
399d1730c3dSJeeja KP 	struct hdac_stream *hstr;
400d1730c3dSJeeja KP 
401d1730c3dSJeeja KP 	stream = get_hdac_ext_stream(substream);
402d1730c3dSJeeja KP 	hstr = hdac_stream(stream);
403d1730c3dSJeeja KP 
404d1730c3dSJeeja KP 	if (!hstr->prepared)
405d1730c3dSJeeja KP 		return -EPIPE;
406d1730c3dSJeeja KP 
407d1730c3dSJeeja KP 	switch (cmd) {
408d1730c3dSJeeja KP 	case SNDRV_PCM_TRIGGER_START:
409d1730c3dSJeeja KP 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
410d1730c3dSJeeja KP 	case SNDRV_PCM_TRIGGER_RESUME:
411d1730c3dSJeeja KP 		start = 1;
412d1730c3dSJeeja KP 		break;
413d1730c3dSJeeja KP 
414d1730c3dSJeeja KP 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
415d1730c3dSJeeja KP 	case SNDRV_PCM_TRIGGER_SUSPEND:
416d1730c3dSJeeja KP 	case SNDRV_PCM_TRIGGER_STOP:
417d1730c3dSJeeja KP 		start = 0;
418d1730c3dSJeeja KP 		break;
419d1730c3dSJeeja KP 
420d1730c3dSJeeja KP 	default:
421d1730c3dSJeeja KP 		return -EINVAL;
422d1730c3dSJeeja KP 	}
423d1730c3dSJeeja KP 
424d1730c3dSJeeja KP 	spin_lock_irqsave(&bus->reg_lock, cookie);
425d1730c3dSJeeja KP 
426d1730c3dSJeeja KP 	if (start) {
427d1730c3dSJeeja KP 		snd_hdac_stream_start(hdac_stream(stream), true);
428d1730c3dSJeeja KP 		snd_hdac_stream_timecounter_init(hstr, 0);
429d1730c3dSJeeja KP 	} else {
430d1730c3dSJeeja KP 		snd_hdac_stream_stop(hdac_stream(stream));
431d1730c3dSJeeja KP 	}
432d1730c3dSJeeja KP 
433d1730c3dSJeeja KP 	spin_unlock_irqrestore(&bus->reg_lock, cookie);
434d1730c3dSJeeja KP 
435d1730c3dSJeeja KP 	return 0;
436d1730c3dSJeeja KP }
437d1730c3dSJeeja KP 
438b663a8c5SJeeja KP static int skl_pcm_trigger(struct snd_pcm_substream *substream, int cmd,
439b663a8c5SJeeja KP 		struct snd_soc_dai *dai)
440b663a8c5SJeeja KP {
441b663a8c5SJeeja KP 	struct skl *skl = get_skl_ctx(dai->dev);
442b663a8c5SJeeja KP 	struct skl_sst *ctx = skl->skl_sst;
443b663a8c5SJeeja KP 	struct skl_module_cfg *mconfig;
4447e3a17d3SJeeja KP 	struct hdac_ext_bus *ebus = get_bus_ctx(substream);
4457e3a17d3SJeeja KP 	struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
4469a655db0SJeeja KP 	struct snd_soc_dapm_widget *w;
447d1730c3dSJeeja KP 	int ret;
448b663a8c5SJeeja KP 
449b663a8c5SJeeja KP 	mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream);
450b663a8c5SJeeja KP 	if (!mconfig)
451b663a8c5SJeeja KP 		return -EIO;
452b663a8c5SJeeja KP 
4539a655db0SJeeja KP 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
4549a655db0SJeeja KP 		w = dai->playback_widget;
4559a655db0SJeeja KP 	else
4569a655db0SJeeja KP 		w = dai->capture_widget;
4579a655db0SJeeja KP 
458b663a8c5SJeeja KP 	switch (cmd) {
4597e3a17d3SJeeja KP 	case SNDRV_PCM_TRIGGER_RESUME:
4609a655db0SJeeja KP 		if (!w->ignore_suspend) {
461748a1d5aSJeeja KP 			/*
4629a655db0SJeeja KP 			 * enable DMA Resume enable bit for the stream, set the
4639a655db0SJeeja KP 			 * dpib & lpib position to resume before starting the
4649a655db0SJeeja KP 			 * DMA
465748a1d5aSJeeja KP 			 */
466748a1d5aSJeeja KP 			snd_hdac_ext_stream_drsm_enable(ebus, true,
467748a1d5aSJeeja KP 						hdac_stream(stream)->index);
4689a655db0SJeeja KP 			snd_hdac_ext_stream_set_dpibr(ebus, stream,
469a700a1e6SJeeja KP 							stream->lpib);
470748a1d5aSJeeja KP 			snd_hdac_ext_stream_set_lpib(stream, stream->lpib);
4719a655db0SJeeja KP 		}
472748a1d5aSJeeja KP 
473d1730c3dSJeeja KP 	case SNDRV_PCM_TRIGGER_START:
474b663a8c5SJeeja KP 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
475d1730c3dSJeeja KP 		/*
476d1730c3dSJeeja KP 		 * Start HOST DMA and Start FE Pipe.This is to make sure that
477d1730c3dSJeeja KP 		 * there are no underrun/overrun in the case when the FE
478d1730c3dSJeeja KP 		 * pipeline is started but there is a delay in starting the
479d1730c3dSJeeja KP 		 * DMA channel on the host.
480d1730c3dSJeeja KP 		 */
481d1730c3dSJeeja KP 		ret = skl_decoupled_trigger(substream, cmd);
482d1730c3dSJeeja KP 		if (ret < 0)
483d1730c3dSJeeja KP 			return ret;
484b663a8c5SJeeja KP 		return skl_run_pipe(ctx, mconfig->pipe);
485d1730c3dSJeeja KP 		break;
486b663a8c5SJeeja KP 
487b663a8c5SJeeja KP 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
488b663a8c5SJeeja KP 	case SNDRV_PCM_TRIGGER_SUSPEND:
489d1730c3dSJeeja KP 	case SNDRV_PCM_TRIGGER_STOP:
490d1730c3dSJeeja KP 		/*
491d1730c3dSJeeja KP 		 * Stop FE Pipe first and stop DMA. This is to make sure that
492d1730c3dSJeeja KP 		 * there are no underrun/overrun in the case if there is a delay
493d1730c3dSJeeja KP 		 * between the two operations.
494d1730c3dSJeeja KP 		 */
495d1730c3dSJeeja KP 		ret = skl_stop_pipe(ctx, mconfig->pipe);
496d1730c3dSJeeja KP 		if (ret < 0)
497d1730c3dSJeeja KP 			return ret;
498d1730c3dSJeeja KP 
499d1730c3dSJeeja KP 		ret = skl_decoupled_trigger(substream, cmd);
5009a655db0SJeeja KP 		if ((cmd == SNDRV_PCM_TRIGGER_SUSPEND) && !w->ignore_suspend) {
501748a1d5aSJeeja KP 			/* save the dpib and lpib positions */
502748a1d5aSJeeja KP 			stream->dpib = readl(ebus->bus.remap_addr +
503748a1d5aSJeeja KP 					AZX_REG_VS_SDXDPIB_XBASE +
504748a1d5aSJeeja KP 					(AZX_REG_VS_SDXDPIB_XINTERVAL *
505748a1d5aSJeeja KP 					hdac_stream(stream)->index));
506748a1d5aSJeeja KP 
507748a1d5aSJeeja KP 			stream->lpib = snd_hdac_stream_get_pos_lpib(
508748a1d5aSJeeja KP 							hdac_stream(stream));
5097e3a17d3SJeeja KP 			snd_hdac_ext_stream_decouple(ebus, stream, false);
510748a1d5aSJeeja KP 		}
511d1730c3dSJeeja KP 		break;
512b663a8c5SJeeja KP 
513b663a8c5SJeeja KP 	default:
514d1730c3dSJeeja KP 		return -EINVAL;
515b663a8c5SJeeja KP 	}
516d1730c3dSJeeja KP 
517d1730c3dSJeeja KP 	return 0;
518b663a8c5SJeeja KP }
519b663a8c5SJeeja KP 
52005057001SJeeja KP static int skl_link_hw_params(struct snd_pcm_substream *substream,
52105057001SJeeja KP 				struct snd_pcm_hw_params *params,
52205057001SJeeja KP 				struct snd_soc_dai *dai)
52305057001SJeeja KP {
52405057001SJeeja KP 	struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev);
52505057001SJeeja KP 	struct hdac_ext_stream *link_dev;
52605057001SJeeja KP 	struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
52705057001SJeeja KP 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
528b663a8c5SJeeja KP 	struct skl_pipe_params p_params = {0};
52912c3be0eSJeeja KP 	struct hdac_ext_link *link;
5301011509dSJeeja KP 	int stream_tag;
53105057001SJeeja KP 
53205057001SJeeja KP 	link_dev = snd_hdac_ext_stream_assign(ebus, substream,
53305057001SJeeja KP 					HDAC_EXT_STREAM_TYPE_LINK);
53405057001SJeeja KP 	if (!link_dev)
53505057001SJeeja KP 		return -EBUSY;
53605057001SJeeja KP 
53705057001SJeeja KP 	snd_soc_dai_set_dma_data(dai, substream, (void *)link_dev);
53805057001SJeeja KP 
539356a383bSKuninori Morimoto 	link = snd_hdac_ext_bus_get_link(ebus, codec_dai->component->name);
54012c3be0eSJeeja KP 	if (!link)
54112c3be0eSJeeja KP 		return -EINVAL;
54212c3be0eSJeeja KP 
5431011509dSJeeja KP 	stream_tag = hdac_stream(link_dev)->stream_tag;
5441011509dSJeeja KP 
54505057001SJeeja KP 	/* set the stream tag in the codec dai dma params  */
5461011509dSJeeja KP 	snd_soc_dai_set_tdm_slot(codec_dai, stream_tag, 0, 0, 0);
547b663a8c5SJeeja KP 
548b663a8c5SJeeja KP 	p_params.s_fmt = snd_pcm_format_width(params_format(params));
549b663a8c5SJeeja KP 	p_params.ch = params_channels(params);
550b663a8c5SJeeja KP 	p_params.s_freq = params_rate(params);
551b663a8c5SJeeja KP 	p_params.stream = substream->stream;
5521011509dSJeeja KP 	p_params.link_dma_id = stream_tag - 1;
55312c3be0eSJeeja KP 	p_params.link_index = link->index;
55412c3be0eSJeeja KP 	p_params.format = params_format(params);
555b663a8c5SJeeja KP 
5567f975a38SJeeja KP 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
5577f975a38SJeeja KP 		p_params.link_bps = codec_dai->driver->playback.sig_bits;
5587f975a38SJeeja KP 	else
5597f975a38SJeeja KP 		p_params.link_bps = codec_dai->driver->capture.sig_bits;
5607f975a38SJeeja KP 
5614bd073f9SJeeja KP 	return skl_tplg_be_update_params(dai, &p_params);
56205057001SJeeja KP }
56305057001SJeeja KP 
56405057001SJeeja KP static int skl_link_pcm_prepare(struct snd_pcm_substream *substream,
56505057001SJeeja KP 		struct snd_soc_dai *dai)
56605057001SJeeja KP {
5672004432fSJeeja KP 	struct skl *skl = get_skl_ctx(dai->dev);
5682004432fSJeeja KP 	struct skl_module_cfg *mconfig = NULL;
56905057001SJeeja KP 
5702004432fSJeeja KP 	/* In case of XRUN recovery, reset the FW pipe to clean state */
5712004432fSJeeja KP 	mconfig = skl_tplg_be_get_cpr_module(dai, substream->stream);
5727cbfdf87SJeeja KP 	if (mconfig && !mconfig->pipe->passthru &&
5737cbfdf87SJeeja KP 		(substream->runtime->status->state == SNDRV_PCM_STATE_XRUN))
5742004432fSJeeja KP 		skl_reset_pipe(skl->skl_sst, mconfig->pipe);
5752004432fSJeeja KP 
57605057001SJeeja KP 	return 0;
57705057001SJeeja KP }
57805057001SJeeja KP 
57905057001SJeeja KP static int skl_link_pcm_trigger(struct snd_pcm_substream *substream,
58005057001SJeeja KP 	int cmd, struct snd_soc_dai *dai)
58105057001SJeeja KP {
58205057001SJeeja KP 	struct hdac_ext_stream *link_dev =
58305057001SJeeja KP 				snd_soc_dai_get_dma_data(dai, substream);
584920982c9SJeeja KP 	struct hdac_ext_bus *ebus = get_bus_ctx(substream);
585920982c9SJeeja KP 	struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
58605057001SJeeja KP 
58705057001SJeeja KP 	dev_dbg(dai->dev, "In %s cmd=%d\n", __func__, cmd);
58805057001SJeeja KP 	switch (cmd) {
589920982c9SJeeja KP 	case SNDRV_PCM_TRIGGER_RESUME:
59005057001SJeeja KP 	case SNDRV_PCM_TRIGGER_START:
59105057001SJeeja KP 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
59205057001SJeeja KP 		snd_hdac_ext_link_stream_start(link_dev);
59305057001SJeeja KP 		break;
59405057001SJeeja KP 
59505057001SJeeja KP 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
59605057001SJeeja KP 	case SNDRV_PCM_TRIGGER_SUSPEND:
59705057001SJeeja KP 	case SNDRV_PCM_TRIGGER_STOP:
59805057001SJeeja KP 		snd_hdac_ext_link_stream_clear(link_dev);
599920982c9SJeeja KP 		if (cmd == SNDRV_PCM_TRIGGER_SUSPEND)
600920982c9SJeeja KP 			snd_hdac_ext_stream_decouple(ebus, stream, false);
60105057001SJeeja KP 		break;
60205057001SJeeja KP 
60305057001SJeeja KP 	default:
60405057001SJeeja KP 		return -EINVAL;
60505057001SJeeja KP 	}
60605057001SJeeja KP 	return 0;
60705057001SJeeja KP }
60805057001SJeeja KP 
60905057001SJeeja KP static int skl_link_hw_free(struct snd_pcm_substream *substream,
61005057001SJeeja KP 		struct snd_soc_dai *dai)
61105057001SJeeja KP {
61205057001SJeeja KP 	struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev);
61305057001SJeeja KP 	struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
61405057001SJeeja KP 	struct hdac_ext_stream *link_dev =
61505057001SJeeja KP 				snd_soc_dai_get_dma_data(dai, substream);
61605057001SJeeja KP 	struct hdac_ext_link *link;
61705057001SJeeja KP 
61805057001SJeeja KP 	dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
61905057001SJeeja KP 
62005057001SJeeja KP 	link_dev->link_prepared = 0;
62105057001SJeeja KP 
622356a383bSKuninori Morimoto 	link = snd_hdac_ext_bus_get_link(ebus, rtd->codec_dai->component->name);
62305057001SJeeja KP 	if (!link)
62405057001SJeeja KP 		return -EINVAL;
62505057001SJeeja KP 
62605057001SJeeja KP 	snd_hdac_ext_link_clear_stream_id(link, hdac_stream(link_dev)->stream_tag);
62705057001SJeeja KP 	snd_hdac_ext_stream_release(link_dev, HDAC_EXT_STREAM_TYPE_LINK);
62805057001SJeeja KP 	return 0;
62905057001SJeeja KP }
63005057001SJeeja KP 
63182e2b1e0SGustavo A. R. Silva static const struct snd_soc_dai_ops skl_pcm_dai_ops = {
632a40e693cSJeeja KP 	.startup = skl_pcm_open,
633a40e693cSJeeja KP 	.shutdown = skl_pcm_close,
634a40e693cSJeeja KP 	.prepare = skl_pcm_prepare,
635a40e693cSJeeja KP 	.hw_params = skl_pcm_hw_params,
636a40e693cSJeeja KP 	.hw_free = skl_pcm_hw_free,
637b663a8c5SJeeja KP 	.trigger = skl_pcm_trigger,
638a40e693cSJeeja KP };
639a40e693cSJeeja KP 
64082e2b1e0SGustavo A. R. Silva static const struct snd_soc_dai_ops skl_dmic_dai_ops = {
641b663a8c5SJeeja KP 	.hw_params = skl_be_hw_params,
642b663a8c5SJeeja KP };
643b663a8c5SJeeja KP 
64482e2b1e0SGustavo A. R. Silva static const struct snd_soc_dai_ops skl_be_ssp_dai_ops = {
645b663a8c5SJeeja KP 	.hw_params = skl_be_hw_params,
64605057001SJeeja KP };
64705057001SJeeja KP 
64882e2b1e0SGustavo A. R. Silva static const struct snd_soc_dai_ops skl_link_dai_ops = {
64905057001SJeeja KP 	.prepare = skl_link_pcm_prepare,
65005057001SJeeja KP 	.hw_params = skl_link_hw_params,
65105057001SJeeja KP 	.hw_free = skl_link_hw_free,
65205057001SJeeja KP 	.trigger = skl_link_pcm_trigger,
65305057001SJeeja KP };
65405057001SJeeja KP 
655c3ae22e3SGuneshwor Singh static struct snd_soc_dai_driver skl_fe_dai[] = {
656a40e693cSJeeja KP {
657a40e693cSJeeja KP 	.name = "System Pin",
658a40e693cSJeeja KP 	.ops = &skl_pcm_dai_ops,
659a40e693cSJeeja KP 	.playback = {
660a40e693cSJeeja KP 		.stream_name = "System Playback",
661a40e693cSJeeja KP 		.channels_min = HDA_MONO,
662a40e693cSJeeja KP 		.channels_max = HDA_STEREO,
663a40e693cSJeeja KP 		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_8000,
664dde53bccSSamaga Krishna 		.formats = SNDRV_PCM_FMTBIT_S16_LE |
665dde53bccSSamaga Krishna 			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE,
6667f975a38SJeeja KP 		.sig_bits = 32,
667a40e693cSJeeja KP 	},
668a40e693cSJeeja KP 	.capture = {
669a40e693cSJeeja KP 		.stream_name = "System Capture",
670a40e693cSJeeja KP 		.channels_min = HDA_MONO,
671a40e693cSJeeja KP 		.channels_max = HDA_STEREO,
672a40e693cSJeeja KP 		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000,
673a40e693cSJeeja KP 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
6747f975a38SJeeja KP 		.sig_bits = 32,
675a40e693cSJeeja KP 	},
676a40e693cSJeeja KP },
677a40e693cSJeeja KP {
678da3cbb40SNaveen Manohar 	.name = "System Pin2",
679da3cbb40SNaveen Manohar 	.ops = &skl_pcm_dai_ops,
680da3cbb40SNaveen Manohar 	.playback = {
681da3cbb40SNaveen Manohar 		.stream_name = "Headset Playback",
682da3cbb40SNaveen Manohar 		.channels_min = HDA_MONO,
683da3cbb40SNaveen Manohar 		.channels_max = HDA_STEREO,
684da3cbb40SNaveen Manohar 		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000 |
685da3cbb40SNaveen Manohar 			SNDRV_PCM_RATE_8000,
686da3cbb40SNaveen Manohar 		.formats = SNDRV_PCM_FMTBIT_S16_LE |
687da3cbb40SNaveen Manohar 			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE,
688da3cbb40SNaveen Manohar 	},
689da3cbb40SNaveen Manohar },
690da3cbb40SNaveen Manohar {
691da3cbb40SNaveen Manohar 	.name = "Echoref Pin",
692da3cbb40SNaveen Manohar 	.ops = &skl_pcm_dai_ops,
693da3cbb40SNaveen Manohar 	.capture = {
694da3cbb40SNaveen Manohar 		.stream_name = "Echoreference Capture",
695da3cbb40SNaveen Manohar 		.channels_min = HDA_STEREO,
696da3cbb40SNaveen Manohar 		.channels_max = HDA_STEREO,
697da3cbb40SNaveen Manohar 		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000 |
698da3cbb40SNaveen Manohar 			SNDRV_PCM_RATE_8000,
699da3cbb40SNaveen Manohar 		.formats = SNDRV_PCM_FMTBIT_S16_LE |
700da3cbb40SNaveen Manohar 			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE,
701da3cbb40SNaveen Manohar 	},
702da3cbb40SNaveen Manohar },
703da3cbb40SNaveen Manohar {
70405057001SJeeja KP 	.name = "Reference Pin",
70505057001SJeeja KP 	.ops = &skl_pcm_dai_ops,
70605057001SJeeja KP 	.capture = {
70705057001SJeeja KP 		.stream_name = "Reference Capture",
70805057001SJeeja KP 		.channels_min = HDA_MONO,
7098f35bf3fSJeeja KP 		.channels_max = HDA_QUAD,
71005057001SJeeja KP 		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000,
71105057001SJeeja KP 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
7127f975a38SJeeja KP 		.sig_bits = 32,
71305057001SJeeja KP 	},
71405057001SJeeja KP },
71505057001SJeeja KP {
716a40e693cSJeeja KP 	.name = "Deepbuffer Pin",
717a40e693cSJeeja KP 	.ops = &skl_pcm_dai_ops,
718a40e693cSJeeja KP 	.playback = {
719a40e693cSJeeja KP 		.stream_name = "Deepbuffer Playback",
720a40e693cSJeeja KP 		.channels_min = HDA_STEREO,
721a40e693cSJeeja KP 		.channels_max = HDA_STEREO,
722a40e693cSJeeja KP 		.rates = SNDRV_PCM_RATE_48000,
723a40e693cSJeeja KP 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
7247f975a38SJeeja KP 		.sig_bits = 32,
725a40e693cSJeeja KP 	},
726a40e693cSJeeja KP },
727a40e693cSJeeja KP {
728a40e693cSJeeja KP 	.name = "LowLatency Pin",
729a40e693cSJeeja KP 	.ops = &skl_pcm_dai_ops,
730a40e693cSJeeja KP 	.playback = {
731a40e693cSJeeja KP 		.stream_name = "Low Latency Playback",
732a40e693cSJeeja KP 		.channels_min = HDA_STEREO,
733a40e693cSJeeja KP 		.channels_max = HDA_STEREO,
734a40e693cSJeeja KP 		.rates = SNDRV_PCM_RATE_48000,
735a40e693cSJeeja KP 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
7367f975a38SJeeja KP 		.sig_bits = 32,
737a40e693cSJeeja KP 	},
738a40e693cSJeeja KP },
7398f35bf3fSJeeja KP {
7408f35bf3fSJeeja KP 	.name = "DMIC Pin",
7418f35bf3fSJeeja KP 	.ops = &skl_pcm_dai_ops,
7428f35bf3fSJeeja KP 	.capture = {
7438f35bf3fSJeeja KP 		.stream_name = "DMIC Capture",
7448f35bf3fSJeeja KP 		.channels_min = HDA_MONO,
7458f35bf3fSJeeja KP 		.channels_max = HDA_QUAD,
7468f35bf3fSJeeja KP 		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000,
7478f35bf3fSJeeja KP 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
7487f975a38SJeeja KP 		.sig_bits = 32,
7498f35bf3fSJeeja KP 	},
7508f35bf3fSJeeja KP },
7518cca87c0SSubhransu S. Prusty {
7528cca87c0SSubhransu S. Prusty 	.name = "HDMI1 Pin",
7538cca87c0SSubhransu S. Prusty 	.ops = &skl_pcm_dai_ops,
7548cca87c0SSubhransu S. Prusty 	.playback = {
7558cca87c0SSubhransu S. Prusty 		.stream_name = "HDMI1 Playback",
7568cca87c0SSubhransu S. Prusty 		.channels_min = HDA_STEREO,
7577e12dc87SSubhransu S. Prusty 		.channels_max = 8,
7588cca87c0SSubhransu S. Prusty 		.rates = SNDRV_PCM_RATE_32000 |	SNDRV_PCM_RATE_44100 |
7598cca87c0SSubhransu S. Prusty 			SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |
7608cca87c0SSubhransu S. Prusty 			SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |
7618cca87c0SSubhransu S. Prusty 			SNDRV_PCM_RATE_192000,
7628cca87c0SSubhransu S. Prusty 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
7638cca87c0SSubhransu S. Prusty 			SNDRV_PCM_FMTBIT_S32_LE,
7647f975a38SJeeja KP 		.sig_bits = 32,
7658cca87c0SSubhransu S. Prusty 	},
7668cca87c0SSubhransu S. Prusty },
7678cca87c0SSubhransu S. Prusty {
7688cca87c0SSubhransu S. Prusty 	.name = "HDMI2 Pin",
7698cca87c0SSubhransu S. Prusty 	.ops = &skl_pcm_dai_ops,
7708cca87c0SSubhransu S. Prusty 	.playback = {
7718cca87c0SSubhransu S. Prusty 		.stream_name = "HDMI2 Playback",
7728cca87c0SSubhransu S. Prusty 		.channels_min = HDA_STEREO,
7737e12dc87SSubhransu S. Prusty 		.channels_max = 8,
7748cca87c0SSubhransu S. Prusty 		.rates = SNDRV_PCM_RATE_32000 |	SNDRV_PCM_RATE_44100 |
7758cca87c0SSubhransu S. Prusty 			SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |
7768cca87c0SSubhransu S. Prusty 			SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |
7778cca87c0SSubhransu S. Prusty 			SNDRV_PCM_RATE_192000,
7788cca87c0SSubhransu S. Prusty 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
7798cca87c0SSubhransu S. Prusty 			SNDRV_PCM_FMTBIT_S32_LE,
7807f975a38SJeeja KP 		.sig_bits = 32,
7818cca87c0SSubhransu S. Prusty 	},
7828cca87c0SSubhransu S. Prusty },
7838cca87c0SSubhransu S. Prusty {
7848cca87c0SSubhransu S. Prusty 	.name = "HDMI3 Pin",
7858cca87c0SSubhransu S. Prusty 	.ops = &skl_pcm_dai_ops,
7868cca87c0SSubhransu S. Prusty 	.playback = {
7878cca87c0SSubhransu S. Prusty 		.stream_name = "HDMI3 Playback",
7888cca87c0SSubhransu S. Prusty 		.channels_min = HDA_STEREO,
7897e12dc87SSubhransu S. Prusty 		.channels_max = 8,
7908cca87c0SSubhransu S. Prusty 		.rates = SNDRV_PCM_RATE_32000 |	SNDRV_PCM_RATE_44100 |
7918cca87c0SSubhransu S. Prusty 			SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |
7928cca87c0SSubhransu S. Prusty 			SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |
7938cca87c0SSubhransu S. Prusty 			SNDRV_PCM_RATE_192000,
7948cca87c0SSubhransu S. Prusty 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
7958cca87c0SSubhransu S. Prusty 			SNDRV_PCM_FMTBIT_S32_LE,
7967f975a38SJeeja KP 		.sig_bits = 32,
7978cca87c0SSubhransu S. Prusty 	},
7988cca87c0SSubhransu S. Prusty },
799c3ae22e3SGuneshwor Singh };
8008f35bf3fSJeeja KP 
80105057001SJeeja KP /* BE CPU  Dais */
802c3ae22e3SGuneshwor Singh static struct snd_soc_dai_driver skl_platform_dai[] = {
80305057001SJeeja KP {
804b663a8c5SJeeja KP 	.name = "SSP0 Pin",
805b663a8c5SJeeja KP 	.ops = &skl_be_ssp_dai_ops,
806b663a8c5SJeeja KP 	.playback = {
807b663a8c5SJeeja KP 		.stream_name = "ssp0 Tx",
808b663a8c5SJeeja KP 		.channels_min = HDA_STEREO,
809b663a8c5SJeeja KP 		.channels_max = HDA_STEREO,
810b663a8c5SJeeja KP 		.rates = SNDRV_PCM_RATE_48000,
811b663a8c5SJeeja KP 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
812b663a8c5SJeeja KP 	},
813b663a8c5SJeeja KP 	.capture = {
814b663a8c5SJeeja KP 		.stream_name = "ssp0 Rx",
815b663a8c5SJeeja KP 		.channels_min = HDA_STEREO,
816b663a8c5SJeeja KP 		.channels_max = HDA_STEREO,
817b663a8c5SJeeja KP 		.rates = SNDRV_PCM_RATE_48000,
818b663a8c5SJeeja KP 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
819b663a8c5SJeeja KP 	},
820b663a8c5SJeeja KP },
821b663a8c5SJeeja KP {
822c80fd4daSJeeja KP 	.name = "SSP1 Pin",
823c80fd4daSJeeja KP 	.ops = &skl_be_ssp_dai_ops,
824c80fd4daSJeeja KP 	.playback = {
825c80fd4daSJeeja KP 		.stream_name = "ssp1 Tx",
826c80fd4daSJeeja KP 		.channels_min = HDA_STEREO,
827c80fd4daSJeeja KP 		.channels_max = HDA_STEREO,
828c80fd4daSJeeja KP 		.rates = SNDRV_PCM_RATE_48000,
829c80fd4daSJeeja KP 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
830c80fd4daSJeeja KP 	},
831c80fd4daSJeeja KP 	.capture = {
832c80fd4daSJeeja KP 		.stream_name = "ssp1 Rx",
833c80fd4daSJeeja KP 		.channels_min = HDA_STEREO,
834c80fd4daSJeeja KP 		.channels_max = HDA_STEREO,
835c80fd4daSJeeja KP 		.rates = SNDRV_PCM_RATE_48000,
836c80fd4daSJeeja KP 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
837c80fd4daSJeeja KP 	},
838c80fd4daSJeeja KP },
839c80fd4daSJeeja KP {
840fcc494afSPardha Saradhi K 	.name = "SSP2 Pin",
841fcc494afSPardha Saradhi K 	.ops = &skl_be_ssp_dai_ops,
842fcc494afSPardha Saradhi K 	.playback = {
843fcc494afSPardha Saradhi K 		.stream_name = "ssp2 Tx",
844fcc494afSPardha Saradhi K 		.channels_min = HDA_STEREO,
845fcc494afSPardha Saradhi K 		.channels_max = HDA_STEREO,
846fcc494afSPardha Saradhi K 		.rates = SNDRV_PCM_RATE_48000,
847fcc494afSPardha Saradhi K 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
848fcc494afSPardha Saradhi K 	},
849fcc494afSPardha Saradhi K 	.capture = {
850fcc494afSPardha Saradhi K 		.stream_name = "ssp2 Rx",
851fcc494afSPardha Saradhi K 		.channels_min = HDA_STEREO,
852fcc494afSPardha Saradhi K 		.channels_max = HDA_STEREO,
853fcc494afSPardha Saradhi K 		.rates = SNDRV_PCM_RATE_48000,
854fcc494afSPardha Saradhi K 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
855fcc494afSPardha Saradhi K 	},
856fcc494afSPardha Saradhi K },
857fcc494afSPardha Saradhi K {
858fcc494afSPardha Saradhi K 	.name = "SSP3 Pin",
859fcc494afSPardha Saradhi K 	.ops = &skl_be_ssp_dai_ops,
860fcc494afSPardha Saradhi K 	.playback = {
861fcc494afSPardha Saradhi K 		.stream_name = "ssp3 Tx",
862fcc494afSPardha Saradhi K 		.channels_min = HDA_STEREO,
863fcc494afSPardha Saradhi K 		.channels_max = HDA_STEREO,
864fcc494afSPardha Saradhi K 		.rates = SNDRV_PCM_RATE_48000,
865fcc494afSPardha Saradhi K 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
866fcc494afSPardha Saradhi K 	},
867fcc494afSPardha Saradhi K 	.capture = {
868fcc494afSPardha Saradhi K 		.stream_name = "ssp3 Rx",
869fcc494afSPardha Saradhi K 		.channels_min = HDA_STEREO,
870fcc494afSPardha Saradhi K 		.channels_max = HDA_STEREO,
871fcc494afSPardha Saradhi K 		.rates = SNDRV_PCM_RATE_48000,
872fcc494afSPardha Saradhi K 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
873fcc494afSPardha Saradhi K 	},
874fcc494afSPardha Saradhi K },
875fcc494afSPardha Saradhi K {
876fcc494afSPardha Saradhi K 	.name = "SSP4 Pin",
877fcc494afSPardha Saradhi K 	.ops = &skl_be_ssp_dai_ops,
878fcc494afSPardha Saradhi K 	.playback = {
879fcc494afSPardha Saradhi K 		.stream_name = "ssp4 Tx",
880fcc494afSPardha Saradhi K 		.channels_min = HDA_STEREO,
881fcc494afSPardha Saradhi K 		.channels_max = HDA_STEREO,
882fcc494afSPardha Saradhi K 		.rates = SNDRV_PCM_RATE_48000,
883fcc494afSPardha Saradhi K 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
884fcc494afSPardha Saradhi K 	},
885fcc494afSPardha Saradhi K 	.capture = {
886fcc494afSPardha Saradhi K 		.stream_name = "ssp4 Rx",
887fcc494afSPardha Saradhi K 		.channels_min = HDA_STEREO,
888fcc494afSPardha Saradhi K 		.channels_max = HDA_STEREO,
889fcc494afSPardha Saradhi K 		.rates = SNDRV_PCM_RATE_48000,
890fcc494afSPardha Saradhi K 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
891fcc494afSPardha Saradhi K 	},
892fcc494afSPardha Saradhi K },
893fcc494afSPardha Saradhi K {
894fcc494afSPardha Saradhi K 	.name = "SSP5 Pin",
895fcc494afSPardha Saradhi K 	.ops = &skl_be_ssp_dai_ops,
896fcc494afSPardha Saradhi K 	.playback = {
897fcc494afSPardha Saradhi K 		.stream_name = "ssp5 Tx",
898fcc494afSPardha Saradhi K 		.channels_min = HDA_STEREO,
899fcc494afSPardha Saradhi K 		.channels_max = HDA_STEREO,
900fcc494afSPardha Saradhi K 		.rates = SNDRV_PCM_RATE_48000,
901fcc494afSPardha Saradhi K 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
902fcc494afSPardha Saradhi K 	},
903fcc494afSPardha Saradhi K 	.capture = {
904fcc494afSPardha Saradhi K 		.stream_name = "ssp5 Rx",
905fcc494afSPardha Saradhi K 		.channels_min = HDA_STEREO,
906fcc494afSPardha Saradhi K 		.channels_max = HDA_STEREO,
907fcc494afSPardha Saradhi K 		.rates = SNDRV_PCM_RATE_48000,
908fcc494afSPardha Saradhi K 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
909fcc494afSPardha Saradhi K 	},
910fcc494afSPardha Saradhi K },
911fcc494afSPardha Saradhi K {
9128cca87c0SSubhransu S. Prusty 	.name = "iDisp1 Pin",
91305057001SJeeja KP 	.ops = &skl_link_dai_ops,
91405057001SJeeja KP 	.playback = {
9158cca87c0SSubhransu S. Prusty 		.stream_name = "iDisp1 Tx",
91605057001SJeeja KP 		.channels_min = HDA_STEREO,
9177e12dc87SSubhransu S. Prusty 		.channels_max = 8,
91805057001SJeeja KP 		.rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|SNDRV_PCM_RATE_48000,
9198cca87c0SSubhransu S. Prusty 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE |
9208cca87c0SSubhransu S. Prusty 			SNDRV_PCM_FMTBIT_S24_LE,
9218cca87c0SSubhransu S. Prusty 	},
9228cca87c0SSubhransu S. Prusty },
9238cca87c0SSubhransu S. Prusty {
9248cca87c0SSubhransu S. Prusty 	.name = "iDisp2 Pin",
9258cca87c0SSubhransu S. Prusty 	.ops = &skl_link_dai_ops,
9268cca87c0SSubhransu S. Prusty 	.playback = {
9278cca87c0SSubhransu S. Prusty 		.stream_name = "iDisp2 Tx",
9288cca87c0SSubhransu S. Prusty 		.channels_min = HDA_STEREO,
9297e12dc87SSubhransu S. Prusty 		.channels_max = 8,
9308cca87c0SSubhransu S. Prusty 		.rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|
9318cca87c0SSubhransu S. Prusty 			SNDRV_PCM_RATE_48000,
9328cca87c0SSubhransu S. Prusty 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE |
9338cca87c0SSubhransu S. Prusty 			SNDRV_PCM_FMTBIT_S24_LE,
9348cca87c0SSubhransu S. Prusty 	},
9358cca87c0SSubhransu S. Prusty },
9368cca87c0SSubhransu S. Prusty {
9378cca87c0SSubhransu S. Prusty 	.name = "iDisp3 Pin",
9388cca87c0SSubhransu S. Prusty 	.ops = &skl_link_dai_ops,
9398cca87c0SSubhransu S. Prusty 	.playback = {
9408cca87c0SSubhransu S. Prusty 		.stream_name = "iDisp3 Tx",
9418cca87c0SSubhransu S. Prusty 		.channels_min = HDA_STEREO,
9427e12dc87SSubhransu S. Prusty 		.channels_max = 8,
9438cca87c0SSubhransu S. Prusty 		.rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|
9448cca87c0SSubhransu S. Prusty 			SNDRV_PCM_RATE_48000,
9458cca87c0SSubhransu S. Prusty 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE |
9468cca87c0SSubhransu S. Prusty 			SNDRV_PCM_FMTBIT_S24_LE,
94705057001SJeeja KP 	},
94805057001SJeeja KP },
94905057001SJeeja KP {
95005057001SJeeja KP 	.name = "DMIC01 Pin",
95105057001SJeeja KP 	.ops = &skl_dmic_dai_ops,
95205057001SJeeja KP 	.capture = {
95305057001SJeeja KP 		.stream_name = "DMIC01 Rx",
9548f35bf3fSJeeja KP 		.channels_min = HDA_MONO,
9558f35bf3fSJeeja KP 		.channels_max = HDA_QUAD,
95605057001SJeeja KP 		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000,
95705057001SJeeja KP 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
95805057001SJeeja KP 	},
95905057001SJeeja KP },
96005057001SJeeja KP {
96105057001SJeeja KP 	.name = "HD-Codec Pin",
96205057001SJeeja KP 	.ops = &skl_link_dai_ops,
96305057001SJeeja KP 	.playback = {
96405057001SJeeja KP 		.stream_name = "HD-Codec Tx",
96505057001SJeeja KP 		.channels_min = HDA_STEREO,
96605057001SJeeja KP 		.channels_max = HDA_STEREO,
96705057001SJeeja KP 		.rates = SNDRV_PCM_RATE_48000,
96805057001SJeeja KP 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
96905057001SJeeja KP 	},
97005057001SJeeja KP 	.capture = {
97105057001SJeeja KP 		.stream_name = "HD-Codec Rx",
97205057001SJeeja KP 		.channels_min = HDA_STEREO,
97305057001SJeeja KP 		.channels_max = HDA_STEREO,
97405057001SJeeja KP 		.rates = SNDRV_PCM_RATE_48000,
97505057001SJeeja KP 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
97605057001SJeeja KP 	},
97705057001SJeeja KP },
978a40e693cSJeeja KP };
979a40e693cSJeeja KP 
980606e21fdSGuneshwor Singh int skl_dai_load(struct snd_soc_component *cmp,
981606e21fdSGuneshwor Singh 		 struct snd_soc_dai_driver *pcm_dai)
982606e21fdSGuneshwor Singh {
983606e21fdSGuneshwor Singh 	pcm_dai->ops = &skl_pcm_dai_ops;
984606e21fdSGuneshwor Singh 
985606e21fdSGuneshwor Singh 	return 0;
986606e21fdSGuneshwor Singh }
987606e21fdSGuneshwor Singh 
988a40e693cSJeeja KP static int skl_platform_open(struct snd_pcm_substream *substream)
989a40e693cSJeeja KP {
990a40e693cSJeeja KP 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
991a40e693cSJeeja KP 	struct snd_soc_dai_link *dai_link = rtd->dai_link;
992a40e693cSJeeja KP 
993a40e693cSJeeja KP 	dev_dbg(rtd->cpu_dai->dev, "In %s:%s\n", __func__,
994a40e693cSJeeja KP 					dai_link->cpu_dai_name);
995a40e693cSJeeja KP 
996a40e693cSJeeja KP 	snd_soc_set_runtime_hwparams(substream, &azx_pcm_hw);
997a40e693cSJeeja KP 
998a40e693cSJeeja KP 	return 0;
999a40e693cSJeeja KP }
1000a40e693cSJeeja KP 
1001b663a8c5SJeeja KP static int skl_coupled_trigger(struct snd_pcm_substream *substream,
1002a40e693cSJeeja KP 					int cmd)
1003a40e693cSJeeja KP {
1004a40e693cSJeeja KP 	struct hdac_ext_bus *ebus = get_bus_ctx(substream);
1005a40e693cSJeeja KP 	struct hdac_bus *bus = ebus_to_hbus(ebus);
1006a40e693cSJeeja KP 	struct hdac_ext_stream *stream;
1007a40e693cSJeeja KP 	struct snd_pcm_substream *s;
1008a40e693cSJeeja KP 	bool start;
1009a40e693cSJeeja KP 	int sbits = 0;
1010a40e693cSJeeja KP 	unsigned long cookie;
1011a40e693cSJeeja KP 	struct hdac_stream *hstr;
1012a40e693cSJeeja KP 
1013a40e693cSJeeja KP 	stream = get_hdac_ext_stream(substream);
1014a40e693cSJeeja KP 	hstr = hdac_stream(stream);
1015a40e693cSJeeja KP 
1016a40e693cSJeeja KP 	dev_dbg(bus->dev, "In %s cmd=%d\n", __func__, cmd);
1017a40e693cSJeeja KP 
1018a40e693cSJeeja KP 	if (!hstr->prepared)
1019a40e693cSJeeja KP 		return -EPIPE;
1020a40e693cSJeeja KP 
1021a40e693cSJeeja KP 	switch (cmd) {
1022a40e693cSJeeja KP 	case SNDRV_PCM_TRIGGER_START:
1023a40e693cSJeeja KP 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
1024a40e693cSJeeja KP 	case SNDRV_PCM_TRIGGER_RESUME:
1025a40e693cSJeeja KP 		start = true;
1026a40e693cSJeeja KP 		break;
1027a40e693cSJeeja KP 
1028a40e693cSJeeja KP 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
1029a40e693cSJeeja KP 	case SNDRV_PCM_TRIGGER_SUSPEND:
1030a40e693cSJeeja KP 	case SNDRV_PCM_TRIGGER_STOP:
1031a40e693cSJeeja KP 		start = false;
1032a40e693cSJeeja KP 		break;
1033a40e693cSJeeja KP 
1034a40e693cSJeeja KP 	default:
1035a40e693cSJeeja KP 		return -EINVAL;
1036a40e693cSJeeja KP 	}
1037a40e693cSJeeja KP 
1038a40e693cSJeeja KP 	snd_pcm_group_for_each_entry(s, substream) {
1039a40e693cSJeeja KP 		if (s->pcm->card != substream->pcm->card)
1040a40e693cSJeeja KP 			continue;
1041a40e693cSJeeja KP 		stream = get_hdac_ext_stream(s);
1042a40e693cSJeeja KP 		sbits |= 1 << hdac_stream(stream)->index;
1043a40e693cSJeeja KP 		snd_pcm_trigger_done(s, substream);
1044a40e693cSJeeja KP 	}
1045a40e693cSJeeja KP 
1046a40e693cSJeeja KP 	spin_lock_irqsave(&bus->reg_lock, cookie);
1047a40e693cSJeeja KP 
1048a40e693cSJeeja KP 	/* first, set SYNC bits of corresponding streams */
1049a40e693cSJeeja KP 	snd_hdac_stream_sync_trigger(hstr, true, sbits, AZX_REG_SSYNC);
1050a40e693cSJeeja KP 
1051a40e693cSJeeja KP 	snd_pcm_group_for_each_entry(s, substream) {
1052a40e693cSJeeja KP 		if (s->pcm->card != substream->pcm->card)
1053a40e693cSJeeja KP 			continue;
1054a40e693cSJeeja KP 		stream = get_hdac_ext_stream(s);
1055a40e693cSJeeja KP 		if (start)
1056a40e693cSJeeja KP 			snd_hdac_stream_start(hdac_stream(stream), true);
1057a40e693cSJeeja KP 		else
1058a40e693cSJeeja KP 			snd_hdac_stream_stop(hdac_stream(stream));
1059a40e693cSJeeja KP 	}
1060a40e693cSJeeja KP 	spin_unlock_irqrestore(&bus->reg_lock, cookie);
1061a40e693cSJeeja KP 
1062a40e693cSJeeja KP 	snd_hdac_stream_sync(hstr, start, sbits);
1063a40e693cSJeeja KP 
1064a40e693cSJeeja KP 	spin_lock_irqsave(&bus->reg_lock, cookie);
1065a40e693cSJeeja KP 
1066a40e693cSJeeja KP 	/* reset SYNC bits */
1067a40e693cSJeeja KP 	snd_hdac_stream_sync_trigger(hstr, false, sbits, AZX_REG_SSYNC);
1068a40e693cSJeeja KP 	if (start)
1069a40e693cSJeeja KP 		snd_hdac_stream_timecounter_init(hstr, sbits);
1070a40e693cSJeeja KP 	spin_unlock_irqrestore(&bus->reg_lock, cookie);
1071a40e693cSJeeja KP 
1072a40e693cSJeeja KP 	return 0;
1073a40e693cSJeeja KP }
1074a40e693cSJeeja KP 
107505057001SJeeja KP static int skl_platform_pcm_trigger(struct snd_pcm_substream *substream,
107605057001SJeeja KP 					int cmd)
107705057001SJeeja KP {
107805057001SJeeja KP 	struct hdac_ext_bus *ebus = get_bus_ctx(substream);
107905057001SJeeja KP 
1080fc94733eSVinod Koul 	if (!(ebus_to_hbus(ebus))->ppcap)
1081b663a8c5SJeeja KP 		return skl_coupled_trigger(substream, cmd);
1082d1730c3dSJeeja KP 
1083d1730c3dSJeeja KP 	return 0;
108405057001SJeeja KP }
108505057001SJeeja KP 
10867b96144dSJeeja KP static snd_pcm_uframes_t skl_platform_pcm_pointer
10877b96144dSJeeja KP 			(struct snd_pcm_substream *substream)
1088a40e693cSJeeja KP {
10897b96144dSJeeja KP 	struct hdac_ext_stream *hstream = get_hdac_ext_stream(substream);
1090ca590c1cSDharageswari R 	struct hdac_ext_bus *ebus = get_bus_ctx(substream);
1091a40e693cSJeeja KP 	unsigned int pos;
1092a40e693cSJeeja KP 
1093ca590c1cSDharageswari R 	/*
1094ca590c1cSDharageswari R 	 * Use DPIB for Playback stream as the periodic DMA Position-in-
1095ca590c1cSDharageswari R 	 * Buffer Writes may be scheduled at the same time or later than
1096ca590c1cSDharageswari R 	 * the MSI and does not guarantee to reflect the Position of the
1097ca590c1cSDharageswari R 	 * last buffer that was transferred. Whereas DPIB register in
1098ca590c1cSDharageswari R 	 * HAD space reflects the actual data that is transferred.
1099ca590c1cSDharageswari R 	 * Use the position buffer for capture, as DPIB write gets
1100ca590c1cSDharageswari R 	 * completed earlier than the actual data written to the DDR.
1101fdd85a05SHardik T Shah 	 *
1102fdd85a05SHardik T Shah 	 * For capture stream following workaround is required to fix the
1103fdd85a05SHardik T Shah 	 * incorrect position reporting.
1104fdd85a05SHardik T Shah 	 *
1105fdd85a05SHardik T Shah 	 * 1. Wait for 20us before reading the DMA position in buffer once
1106fdd85a05SHardik T Shah 	 * the interrupt is generated for stream completion as update happens
1107fdd85a05SHardik T Shah 	 * on the HDA frame boundary i.e. 20.833uSec.
1108fdd85a05SHardik T Shah 	 * 2. Read DPIB register to flush the DMA position value. This dummy
1109fdd85a05SHardik T Shah 	 * read is required to flush DMA position value.
1110fdd85a05SHardik T Shah 	 * 3. Read the DMA Position-in-Buffer. This value now will be equal to
1111fdd85a05SHardik T Shah 	 * or greater than period boundary.
1112ca590c1cSDharageswari R 	 */
1113fdd85a05SHardik T Shah 
1114fdd85a05SHardik T Shah 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
1115ca590c1cSDharageswari R 		pos = readl(ebus->bus.remap_addr + AZX_REG_VS_SDXDPIB_XBASE +
1116ca590c1cSDharageswari R 				(AZX_REG_VS_SDXDPIB_XINTERVAL *
1117ca590c1cSDharageswari R 				hdac_stream(hstream)->index));
1118fdd85a05SHardik T Shah 	} else {
1119fdd85a05SHardik T Shah 		udelay(20);
1120fdd85a05SHardik T Shah 		readl(ebus->bus.remap_addr +
1121fdd85a05SHardik T Shah 				AZX_REG_VS_SDXDPIB_XBASE +
1122fdd85a05SHardik T Shah 				(AZX_REG_VS_SDXDPIB_XINTERVAL *
1123fdd85a05SHardik T Shah 				 hdac_stream(hstream)->index));
1124a40e693cSJeeja KP 		pos = snd_hdac_stream_get_pos_posbuf(hdac_stream(hstream));
1125fdd85a05SHardik T Shah 	}
1126a40e693cSJeeja KP 
1127a40e693cSJeeja KP 	if (pos >= hdac_stream(hstream)->bufsize)
1128a40e693cSJeeja KP 		pos = 0;
1129a40e693cSJeeja KP 
11307b96144dSJeeja KP 	return bytes_to_frames(substream->runtime, pos);
1131a40e693cSJeeja KP }
1132a40e693cSJeeja KP 
1133a40e693cSJeeja KP static u64 skl_adjust_codec_delay(struct snd_pcm_substream *substream,
1134a40e693cSJeeja KP 				u64 nsec)
1135a40e693cSJeeja KP {
1136a40e693cSJeeja KP 	struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
1137a40e693cSJeeja KP 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
1138a40e693cSJeeja KP 	u64 codec_frames, codec_nsecs;
1139a40e693cSJeeja KP 
1140a40e693cSJeeja KP 	if (!codec_dai->driver->ops->delay)
1141a40e693cSJeeja KP 		return nsec;
1142a40e693cSJeeja KP 
1143a40e693cSJeeja KP 	codec_frames = codec_dai->driver->ops->delay(substream, codec_dai);
1144a40e693cSJeeja KP 	codec_nsecs = div_u64(codec_frames * 1000000000LL,
1145a40e693cSJeeja KP 			      substream->runtime->rate);
1146a40e693cSJeeja KP 
1147a40e693cSJeeja KP 	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
1148a40e693cSJeeja KP 		return nsec + codec_nsecs;
1149a40e693cSJeeja KP 
1150a40e693cSJeeja KP 	return (nsec > codec_nsecs) ? nsec - codec_nsecs : 0;
1151a40e693cSJeeja KP }
1152a40e693cSJeeja KP 
1153a40e693cSJeeja KP static int skl_get_time_info(struct snd_pcm_substream *substream,
1154a40e693cSJeeja KP 			struct timespec *system_ts, struct timespec *audio_ts,
1155a40e693cSJeeja KP 			struct snd_pcm_audio_tstamp_config *audio_tstamp_config,
1156a40e693cSJeeja KP 			struct snd_pcm_audio_tstamp_report *audio_tstamp_report)
1157a40e693cSJeeja KP {
1158a40e693cSJeeja KP 	struct hdac_ext_stream *sstream = get_hdac_ext_stream(substream);
1159a40e693cSJeeja KP 	struct hdac_stream *hstr = hdac_stream(sstream);
1160a40e693cSJeeja KP 	u64 nsec;
1161a40e693cSJeeja KP 
1162a40e693cSJeeja KP 	if ((substream->runtime->hw.info & SNDRV_PCM_INFO_HAS_LINK_ATIME) &&
1163a40e693cSJeeja KP 		(audio_tstamp_config->type_requested == SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK)) {
1164a40e693cSJeeja KP 
1165a40e693cSJeeja KP 		snd_pcm_gettime(substream->runtime, system_ts);
1166a40e693cSJeeja KP 
1167a40e693cSJeeja KP 		nsec = timecounter_read(&hstr->tc);
1168a40e693cSJeeja KP 		nsec = div_u64(nsec, 3); /* can be optimized */
1169a40e693cSJeeja KP 		if (audio_tstamp_config->report_delay)
1170a40e693cSJeeja KP 			nsec = skl_adjust_codec_delay(substream, nsec);
1171a40e693cSJeeja KP 
1172a40e693cSJeeja KP 		*audio_ts = ns_to_timespec(nsec);
1173a40e693cSJeeja KP 
1174a40e693cSJeeja KP 		audio_tstamp_report->actual_type = SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK;
1175a40e693cSJeeja KP 		audio_tstamp_report->accuracy_report = 1; /* rest of struct is valid */
1176a40e693cSJeeja KP 		audio_tstamp_report->accuracy = 42; /* 24MHzWallClk == 42ns resolution */
1177a40e693cSJeeja KP 
1178a40e693cSJeeja KP 	} else {
1179a40e693cSJeeja KP 		audio_tstamp_report->actual_type = SNDRV_PCM_AUDIO_TSTAMP_TYPE_DEFAULT;
1180a40e693cSJeeja KP 	}
1181a40e693cSJeeja KP 
1182a40e693cSJeeja KP 	return 0;
1183a40e693cSJeeja KP }
1184a40e693cSJeeja KP 
1185115c7254SJulia Lawall static const struct snd_pcm_ops skl_platform_ops = {
1186a40e693cSJeeja KP 	.open = skl_platform_open,
1187a40e693cSJeeja KP 	.ioctl = snd_pcm_lib_ioctl,
1188a40e693cSJeeja KP 	.trigger = skl_platform_pcm_trigger,
1189a40e693cSJeeja KP 	.pointer = skl_platform_pcm_pointer,
1190a40e693cSJeeja KP 	.get_time_info =  skl_get_time_info,
1191a40e693cSJeeja KP 	.mmap = snd_pcm_lib_default_mmap,
1192a40e693cSJeeja KP 	.page = snd_pcm_sgbuf_ops_page,
1193a40e693cSJeeja KP };
1194a40e693cSJeeja KP 
1195a40e693cSJeeja KP static void skl_pcm_free(struct snd_pcm *pcm)
1196a40e693cSJeeja KP {
1197a40e693cSJeeja KP 	snd_pcm_lib_preallocate_free_for_all(pcm);
1198a40e693cSJeeja KP }
1199a40e693cSJeeja KP 
1200a40e693cSJeeja KP #define MAX_PREALLOC_SIZE	(32 * 1024 * 1024)
1201a40e693cSJeeja KP 
1202a40e693cSJeeja KP static int skl_pcm_new(struct snd_soc_pcm_runtime *rtd)
1203a40e693cSJeeja KP {
1204a40e693cSJeeja KP 	struct snd_soc_dai *dai = rtd->cpu_dai;
1205a40e693cSJeeja KP 	struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev);
1206a40e693cSJeeja KP 	struct snd_pcm *pcm = rtd->pcm;
1207a40e693cSJeeja KP 	unsigned int size;
1208a40e693cSJeeja KP 	int retval = 0;
1209a40e693cSJeeja KP 	struct skl *skl = ebus_to_skl(ebus);
1210a40e693cSJeeja KP 
1211a40e693cSJeeja KP 	if (dai->driver->playback.channels_min ||
1212a40e693cSJeeja KP 		dai->driver->capture.channels_min) {
1213a40e693cSJeeja KP 		/* buffer pre-allocation */
1214a40e693cSJeeja KP 		size = CONFIG_SND_HDA_PREALLOC_SIZE * 1024;
1215a40e693cSJeeja KP 		if (size > MAX_PREALLOC_SIZE)
1216a40e693cSJeeja KP 			size = MAX_PREALLOC_SIZE;
1217a40e693cSJeeja KP 		retval = snd_pcm_lib_preallocate_pages_for_all(pcm,
1218a40e693cSJeeja KP 						SNDRV_DMA_TYPE_DEV_SG,
1219a40e693cSJeeja KP 						snd_dma_pci_data(skl->pci),
1220a40e693cSJeeja KP 						size, MAX_PREALLOC_SIZE);
1221a40e693cSJeeja KP 		if (retval) {
122208458871SColin Ian King 			dev_err(dai->dev, "dma buffer allocation fail\n");
1223a40e693cSJeeja KP 			return retval;
1224a40e693cSJeeja KP 		}
1225a40e693cSJeeja KP 	}
1226a40e693cSJeeja KP 
1227a40e693cSJeeja KP 	return retval;
1228a40e693cSJeeja KP }
1229a40e693cSJeeja KP 
1230b26199eaSJeeja KP static int skl_get_module_info(struct skl *skl, struct skl_module_cfg *mconfig)
1231b26199eaSJeeja KP {
1232b26199eaSJeeja KP 	struct skl_sst *ctx = skl->skl_sst;
123391fe0e70SJeeja KP 	struct skl_module_inst_id *pin_id;
123491fe0e70SJeeja KP 	uuid_le *uuid_mod, *uuid_tplg;
123591fe0e70SJeeja KP 	struct skl_module *skl_module;
1236b26199eaSJeeja KP 	struct uuid_module *module;
123791fe0e70SJeeja KP 	int i, ret = -EIO;
1238b26199eaSJeeja KP 
1239b26199eaSJeeja KP 	uuid_mod = (uuid_le *)mconfig->guid;
1240b26199eaSJeeja KP 
1241b26199eaSJeeja KP 	if (list_empty(&ctx->uuid_list)) {
1242b26199eaSJeeja KP 		dev_err(ctx->dev, "Module list is empty\n");
1243b26199eaSJeeja KP 		return -EIO;
1244b26199eaSJeeja KP 	}
1245b26199eaSJeeja KP 
1246b26199eaSJeeja KP 	list_for_each_entry(module, &ctx->uuid_list, list) {
1247b26199eaSJeeja KP 		if (uuid_le_cmp(*uuid_mod, module->uuid) == 0) {
1248b26199eaSJeeja KP 			mconfig->id.module_id = module->id;
1249f6fa56e2SRamesh Babu 			if (mconfig->module)
1250f6fa56e2SRamesh Babu 				mconfig->module->loadable = module->is_loadable;
125191fe0e70SJeeja KP 			ret = 0;
125291fe0e70SJeeja KP 			break;
1253b26199eaSJeeja KP 		}
1254b26199eaSJeeja KP 	}
1255b26199eaSJeeja KP 
125691fe0e70SJeeja KP 	if (ret)
125791fe0e70SJeeja KP 		return ret;
125891fe0e70SJeeja KP 
125991fe0e70SJeeja KP 	uuid_mod = &module->uuid;
126091fe0e70SJeeja KP 	ret = -EIO;
126191fe0e70SJeeja KP 	for (i = 0; i < skl->nr_modules; i++) {
126291fe0e70SJeeja KP 		skl_module = skl->modules[i];
126391fe0e70SJeeja KP 		uuid_tplg = &skl_module->uuid;
126491fe0e70SJeeja KP 		if (!uuid_le_cmp(*uuid_mod, *uuid_tplg)) {
126591fe0e70SJeeja KP 			mconfig->module = skl_module;
126691fe0e70SJeeja KP 			ret = 0;
126791fe0e70SJeeja KP 			break;
126891fe0e70SJeeja KP 		}
126991fe0e70SJeeja KP 	}
127091fe0e70SJeeja KP 	if (skl->nr_modules && ret)
127191fe0e70SJeeja KP 		return ret;
127291fe0e70SJeeja KP 
127391fe0e70SJeeja KP 	list_for_each_entry(module, &ctx->uuid_list, list) {
127491fe0e70SJeeja KP 		for (i = 0; i < MAX_IN_QUEUE; i++) {
127591fe0e70SJeeja KP 			pin_id = &mconfig->m_in_pin[i].id;
127691fe0e70SJeeja KP 			if (!uuid_le_cmp(pin_id->mod_uuid, module->uuid))
127791fe0e70SJeeja KP 				pin_id->module_id = module->id;
127891fe0e70SJeeja KP 		}
127991fe0e70SJeeja KP 
128091fe0e70SJeeja KP 		for (i = 0; i < MAX_OUT_QUEUE; i++) {
128191fe0e70SJeeja KP 			pin_id = &mconfig->m_out_pin[i].id;
128291fe0e70SJeeja KP 			if (!uuid_le_cmp(pin_id->mod_uuid, module->uuid))
128391fe0e70SJeeja KP 				pin_id->module_id = module->id;
128491fe0e70SJeeja KP 		}
128591fe0e70SJeeja KP 	}
128691fe0e70SJeeja KP 
128791fe0e70SJeeja KP 	return 0;
1288b26199eaSJeeja KP }
1289b26199eaSJeeja KP 
129064cb1d0aSVinod Koul static int skl_populate_modules(struct skl *skl)
129164cb1d0aSVinod Koul {
129264cb1d0aSVinod Koul 	struct skl_pipeline *p;
129364cb1d0aSVinod Koul 	struct skl_pipe_module *m;
129464cb1d0aSVinod Koul 	struct snd_soc_dapm_widget *w;
129564cb1d0aSVinod Koul 	struct skl_module_cfg *mconfig;
1296b26199eaSJeeja KP 	int ret = 0;
129764cb1d0aSVinod Koul 
129864cb1d0aSVinod Koul 	list_for_each_entry(p, &skl->ppl_list, node) {
129964cb1d0aSVinod Koul 		list_for_each_entry(m, &p->pipe->w_list, node) {
130064cb1d0aSVinod Koul 			w = m->w;
130164cb1d0aSVinod Koul 			mconfig = w->priv;
130264cb1d0aSVinod Koul 
1303b26199eaSJeeja KP 			ret = skl_get_module_info(skl, mconfig);
130464cb1d0aSVinod Koul 			if (ret < 0) {
130564cb1d0aSVinod Koul 				dev_err(skl->skl_sst->dev,
1306b26199eaSJeeja KP 					"query module info failed\n");
1307b26199eaSJeeja KP 				return ret;
130864cb1d0aSVinod Koul 			}
130964cb1d0aSVinod Koul 		}
131064cb1d0aSVinod Koul 	}
1311b26199eaSJeeja KP 
131264cb1d0aSVinod Koul 	return ret;
131364cb1d0aSVinod Koul }
131464cb1d0aSVinod Koul 
1315b663a8c5SJeeja KP static int skl_platform_soc_probe(struct snd_soc_platform *platform)
1316b663a8c5SJeeja KP {
1317b663a8c5SJeeja KP 	struct hdac_ext_bus *ebus = dev_get_drvdata(platform->dev);
1318fe3f4442SDharageswari R 	struct skl *skl = ebus_to_skl(ebus);
131978cdbbdaSVinod Koul 	const struct skl_dsp_ops *ops;
1320fe3f4442SDharageswari R 	int ret;
1321b663a8c5SJeeja KP 
132278cdbbdaSVinod Koul 	pm_runtime_get_sync(platform->dev);
1323ec8ae570SVinod Koul 	if ((ebus_to_hbus(ebus))->ppcap) {
13245cdf6c09SVinod Koul 		skl->platform = platform;
13255cdf6c09SVinod Koul 
13265cdf6c09SVinod Koul 		/* init debugfs */
13275cdf6c09SVinod Koul 		skl->debugfs = skl_debugfs_init(skl);
13285cdf6c09SVinod Koul 
1329fe3f4442SDharageswari R 		ret = skl_tplg_init(platform, ebus);
1330fe3f4442SDharageswari R 		if (ret < 0) {
1331fe3f4442SDharageswari R 			dev_err(platform->dev, "Failed to init topology!\n");
1332fe3f4442SDharageswari R 			return ret;
1333fe3f4442SDharageswari R 		}
133478cdbbdaSVinod Koul 
133578cdbbdaSVinod Koul 		/* load the firmwares, since all is set */
133678cdbbdaSVinod Koul 		ops = skl_get_dsp_ops(skl->pci->device);
133778cdbbdaSVinod Koul 		if (!ops)
133878cdbbdaSVinod Koul 			return -EIO;
133978cdbbdaSVinod Koul 
134078cdbbdaSVinod Koul 		if (skl->skl_sst->is_first_boot == false) {
134178cdbbdaSVinod Koul 			dev_err(platform->dev, "DSP reports first boot done!!!\n");
134278cdbbdaSVinod Koul 			return -EIO;
1343fe3f4442SDharageswari R 		}
1344b663a8c5SJeeja KP 
1345d5cc0a1fSPardha Saradhi K 		/* disable dynamic clock gating during fw and lib download */
1346d5cc0a1fSPardha Saradhi K 		skl->skl_sst->enable_miscbdcge(platform->dev, false);
1347d5cc0a1fSPardha Saradhi K 
134878cdbbdaSVinod Koul 		ret = ops->init_fw(platform->dev, skl->skl_sst);
1349d5cc0a1fSPardha Saradhi K 		skl->skl_sst->enable_miscbdcge(platform->dev, true);
135078cdbbdaSVinod Koul 		if (ret < 0) {
135178cdbbdaSVinod Koul 			dev_err(platform->dev, "Failed to boot first fw: %d\n", ret);
135278cdbbdaSVinod Koul 			return ret;
135378cdbbdaSVinod Koul 		}
135464cb1d0aSVinod Koul 		skl_populate_modules(skl);
1355a26a3f53SPardha Saradhi K 		skl->skl_sst->update_d0i3c = skl_update_d0i3c;
1356cb729d80SG Kranthi 		skl_dsp_enable_notification(skl->skl_sst, false);
13579452314dSPradeep Tewani 
13589452314dSPradeep Tewani 		if (skl->cfg.astate_cfg != NULL) {
13599452314dSPradeep Tewani 			skl_dsp_set_astate_cfg(skl->skl_sst,
13609452314dSPradeep Tewani 					skl->cfg.astate_cfg->count,
13619452314dSPradeep Tewani 					skl->cfg.astate_cfg);
13629452314dSPradeep Tewani 		}
136378cdbbdaSVinod Koul 	}
136478cdbbdaSVinod Koul 	pm_runtime_mark_last_busy(platform->dev);
136578cdbbdaSVinod Koul 	pm_runtime_put_autosuspend(platform->dev);
136678cdbbdaSVinod Koul 
1367b663a8c5SJeeja KP 	return 0;
1368b663a8c5SJeeja KP }
136980cc4df8SBhumika Goyal static const struct snd_soc_platform_driver skl_platform_drv  = {
1370b663a8c5SJeeja KP 	.probe		= skl_platform_soc_probe,
1371a40e693cSJeeja KP 	.ops		= &skl_platform_ops,
1372a40e693cSJeeja KP 	.pcm_new	= skl_pcm_new,
1373a40e693cSJeeja KP 	.pcm_free	= skl_pcm_free,
1374a40e693cSJeeja KP };
1375a40e693cSJeeja KP 
1376a40e693cSJeeja KP static const struct snd_soc_component_driver skl_component = {
1377a40e693cSJeeja KP 	.name           = "pcm",
1378a40e693cSJeeja KP };
1379a40e693cSJeeja KP 
1380a40e693cSJeeja KP int skl_platform_register(struct device *dev)
1381a40e693cSJeeja KP {
1382a40e693cSJeeja KP 	int ret;
1383b663a8c5SJeeja KP 	struct hdac_ext_bus *ebus = dev_get_drvdata(dev);
1384b663a8c5SJeeja KP 	struct skl *skl = ebus_to_skl(ebus);
1385c3ae22e3SGuneshwor Singh 	struct snd_soc_dai_driver *dais;
1386c3ae22e3SGuneshwor Singh 	int num_dais = ARRAY_SIZE(skl_platform_dai);
1387b663a8c5SJeeja KP 
1388b663a8c5SJeeja KP 	INIT_LIST_HEAD(&skl->ppl_list);
1389b8c722ddSJeeja KP 	INIT_LIST_HEAD(&skl->bind_list);
1390a40e693cSJeeja KP 
1391a40e693cSJeeja KP 	ret = snd_soc_register_platform(dev, &skl_platform_drv);
1392a40e693cSJeeja KP 	if (ret) {
1393a40e693cSJeeja KP 		dev_err(dev, "soc platform registration failed %d\n", ret);
1394a40e693cSJeeja KP 		return ret;
1395a40e693cSJeeja KP 	}
1396c3ae22e3SGuneshwor Singh 
1397c3ae22e3SGuneshwor Singh 	skl->dais = kmemdup(skl_platform_dai, sizeof(skl_platform_dai),
1398c3ae22e3SGuneshwor Singh 			    GFP_KERNEL);
1399c3ae22e3SGuneshwor Singh 	if (!skl->dais) {
1400c3ae22e3SGuneshwor Singh 		ret = -ENOMEM;
1401c3ae22e3SGuneshwor Singh 		goto err;
1402a40e693cSJeeja KP 	}
1403a40e693cSJeeja KP 
1404c3ae22e3SGuneshwor Singh 	if (!skl->use_tplg_pcm) {
1405c3ae22e3SGuneshwor Singh 		dais = krealloc(skl->dais, sizeof(skl_fe_dai) +
1406c3ae22e3SGuneshwor Singh 				sizeof(skl_platform_dai), GFP_KERNEL);
1407c3ae22e3SGuneshwor Singh 		if (!dais) {
1408c3ae22e3SGuneshwor Singh 			ret = -ENOMEM;
1409c3ae22e3SGuneshwor Singh 			goto err;
1410c3ae22e3SGuneshwor Singh 		}
1411c3ae22e3SGuneshwor Singh 
1412c3ae22e3SGuneshwor Singh 		skl->dais = dais;
1413c3ae22e3SGuneshwor Singh 		memcpy(&skl->dais[ARRAY_SIZE(skl_platform_dai)], skl_fe_dai,
1414c3ae22e3SGuneshwor Singh 		       sizeof(skl_fe_dai));
1415c3ae22e3SGuneshwor Singh 		num_dais += ARRAY_SIZE(skl_fe_dai);
1416c3ae22e3SGuneshwor Singh 	}
1417c3ae22e3SGuneshwor Singh 
1418c3ae22e3SGuneshwor Singh 	ret = snd_soc_register_component(dev, &skl_component,
1419c3ae22e3SGuneshwor Singh 					 skl->dais, num_dais);
1420c3ae22e3SGuneshwor Singh 	if (ret) {
1421c3ae22e3SGuneshwor Singh 		dev_err(dev, "soc component registration failed %d\n", ret);
1422c3ae22e3SGuneshwor Singh 		goto err;
1423c3ae22e3SGuneshwor Singh 	}
1424c3ae22e3SGuneshwor Singh 
1425c3ae22e3SGuneshwor Singh 	return 0;
1426c3ae22e3SGuneshwor Singh err:
1427c3ae22e3SGuneshwor Singh 	snd_soc_unregister_platform(dev);
1428a40e693cSJeeja KP 	return ret;
1429a40e693cSJeeja KP 
1430a40e693cSJeeja KP }
1431a40e693cSJeeja KP 
1432a40e693cSJeeja KP int skl_platform_unregister(struct device *dev)
1433a40e693cSJeeja KP {
1434b8c722ddSJeeja KP 	struct hdac_ext_bus *ebus = dev_get_drvdata(dev);
1435b8c722ddSJeeja KP 	struct skl *skl = ebus_to_skl(ebus);
1436550b349aSDan Carpenter 	struct skl_module_deferred_bind *modules, *tmp;
1437b8c722ddSJeeja KP 
1438b8c722ddSJeeja KP 	if (!list_empty(&skl->bind_list)) {
1439550b349aSDan Carpenter 		list_for_each_entry_safe(modules, tmp, &skl->bind_list, node) {
1440b8c722ddSJeeja KP 			list_del(&modules->node);
1441b8c722ddSJeeja KP 			kfree(modules);
1442b8c722ddSJeeja KP 		}
1443b8c722ddSJeeja KP 	}
1444b8c722ddSJeeja KP 
1445a40e693cSJeeja KP 	snd_soc_unregister_component(dev);
1446a40e693cSJeeja KP 	snd_soc_unregister_platform(dev);
1447c3ae22e3SGuneshwor Singh 	kfree(skl->dais);
1448c3ae22e3SGuneshwor Singh 
1449a40e693cSJeeja KP 	return 0;
1450a40e693cSJeeja KP }
1451