162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *  skl-pcm.c -ASoC HDA Platform driver file implementing PCM functionality
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci *  Copyright (C) 2014-2015 Intel Corp
662306a36Sopenharmony_ci *  Author:  Jeeja KP <jeeja.kp@intel.com>
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
962306a36Sopenharmony_ci *
1062306a36Sopenharmony_ci * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1162306a36Sopenharmony_ci */
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include <linux/pci.h>
1462306a36Sopenharmony_ci#include <linux/pm_runtime.h>
1562306a36Sopenharmony_ci#include <linux/delay.h>
1662306a36Sopenharmony_ci#include <sound/hdaudio.h>
1762306a36Sopenharmony_ci#include <sound/pcm_params.h>
1862306a36Sopenharmony_ci#include <sound/soc.h>
1962306a36Sopenharmony_ci#include "skl.h"
2062306a36Sopenharmony_ci#include "skl-topology.h"
2162306a36Sopenharmony_ci#include "skl-sst-dsp.h"
2262306a36Sopenharmony_ci#include "skl-sst-ipc.h"
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci#define HDA_MONO 1
2562306a36Sopenharmony_ci#define HDA_STEREO 2
2662306a36Sopenharmony_ci#define HDA_QUAD 4
2762306a36Sopenharmony_ci#define HDA_MAX 8
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_cistatic const struct snd_pcm_hardware azx_pcm_hw = {
3062306a36Sopenharmony_ci	.info =			(SNDRV_PCM_INFO_MMAP |
3162306a36Sopenharmony_ci				 SNDRV_PCM_INFO_INTERLEAVED |
3262306a36Sopenharmony_ci				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
3362306a36Sopenharmony_ci				 SNDRV_PCM_INFO_MMAP_VALID |
3462306a36Sopenharmony_ci				 SNDRV_PCM_INFO_PAUSE |
3562306a36Sopenharmony_ci				 SNDRV_PCM_INFO_RESUME |
3662306a36Sopenharmony_ci				 SNDRV_PCM_INFO_SYNC_START |
3762306a36Sopenharmony_ci				 SNDRV_PCM_INFO_HAS_WALL_CLOCK | /* legacy */
3862306a36Sopenharmony_ci				 SNDRV_PCM_INFO_HAS_LINK_ATIME |
3962306a36Sopenharmony_ci				 SNDRV_PCM_INFO_NO_PERIOD_WAKEUP),
4062306a36Sopenharmony_ci	.formats =		SNDRV_PCM_FMTBIT_S16_LE |
4162306a36Sopenharmony_ci				SNDRV_PCM_FMTBIT_S32_LE |
4262306a36Sopenharmony_ci				SNDRV_PCM_FMTBIT_S24_LE,
4362306a36Sopenharmony_ci	.rates =		SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000 |
4462306a36Sopenharmony_ci				SNDRV_PCM_RATE_8000,
4562306a36Sopenharmony_ci	.rate_min =		8000,
4662306a36Sopenharmony_ci	.rate_max =		48000,
4762306a36Sopenharmony_ci	.channels_min =		1,
4862306a36Sopenharmony_ci	.channels_max =		8,
4962306a36Sopenharmony_ci	.buffer_bytes_max =	AZX_MAX_BUF_SIZE,
5062306a36Sopenharmony_ci	.period_bytes_min =	128,
5162306a36Sopenharmony_ci	.period_bytes_max =	AZX_MAX_BUF_SIZE / 2,
5262306a36Sopenharmony_ci	.periods_min =		2,
5362306a36Sopenharmony_ci	.periods_max =		AZX_MAX_FRAG,
5462306a36Sopenharmony_ci	.fifo_size =		0,
5562306a36Sopenharmony_ci};
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_cistatic inline
5862306a36Sopenharmony_cistruct hdac_ext_stream *get_hdac_ext_stream(struct snd_pcm_substream *substream)
5962306a36Sopenharmony_ci{
6062306a36Sopenharmony_ci	return substream->runtime->private_data;
6162306a36Sopenharmony_ci}
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_cistatic struct hdac_bus *get_bus_ctx(struct snd_pcm_substream *substream)
6462306a36Sopenharmony_ci{
6562306a36Sopenharmony_ci	struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
6662306a36Sopenharmony_ci	struct hdac_stream *hstream = hdac_stream(stream);
6762306a36Sopenharmony_ci	struct hdac_bus *bus = hstream->bus;
6862306a36Sopenharmony_ci	return bus;
6962306a36Sopenharmony_ci}
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_cistatic int skl_substream_alloc_pages(struct hdac_bus *bus,
7262306a36Sopenharmony_ci				 struct snd_pcm_substream *substream,
7362306a36Sopenharmony_ci				 size_t size)
7462306a36Sopenharmony_ci{
7562306a36Sopenharmony_ci	struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	hdac_stream(stream)->bufsize = 0;
7862306a36Sopenharmony_ci	hdac_stream(stream)->period_bytes = 0;
7962306a36Sopenharmony_ci	hdac_stream(stream)->format_val = 0;
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci	return 0;
8262306a36Sopenharmony_ci}
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_cistatic void skl_set_pcm_constrains(struct hdac_bus *bus,
8562306a36Sopenharmony_ci				 struct snd_pcm_runtime *runtime)
8662306a36Sopenharmony_ci{
8762306a36Sopenharmony_ci	snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci	/* avoid wrap-around with wall-clock */
9062306a36Sopenharmony_ci	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_TIME,
9162306a36Sopenharmony_ci				     20, 178000000);
9262306a36Sopenharmony_ci}
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_cistatic enum hdac_ext_stream_type skl_get_host_stream_type(struct hdac_bus *bus)
9562306a36Sopenharmony_ci{
9662306a36Sopenharmony_ci	if (bus->ppcap)
9762306a36Sopenharmony_ci		return HDAC_EXT_STREAM_TYPE_HOST;
9862306a36Sopenharmony_ci	else
9962306a36Sopenharmony_ci		return HDAC_EXT_STREAM_TYPE_COUPLED;
10062306a36Sopenharmony_ci}
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci/*
10362306a36Sopenharmony_ci * check if the stream opened is marked as ignore_suspend by machine, if so
10462306a36Sopenharmony_ci * then enable suspend_active refcount
10562306a36Sopenharmony_ci *
10662306a36Sopenharmony_ci * The count supend_active does not need lock as it is used in open/close
10762306a36Sopenharmony_ci * and suspend context
10862306a36Sopenharmony_ci */
10962306a36Sopenharmony_cistatic void skl_set_suspend_active(struct snd_pcm_substream *substream,
11062306a36Sopenharmony_ci					 struct snd_soc_dai *dai, bool enable)
11162306a36Sopenharmony_ci{
11262306a36Sopenharmony_ci	struct hdac_bus *bus = dev_get_drvdata(dai->dev);
11362306a36Sopenharmony_ci	struct snd_soc_dapm_widget *w;
11462306a36Sopenharmony_ci	struct skl_dev *skl = bus_to_skl(bus);
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci	w = snd_soc_dai_get_widget(dai, substream->stream);
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci	if (w->ignore_suspend && enable)
11962306a36Sopenharmony_ci		skl->supend_active++;
12062306a36Sopenharmony_ci	else if (w->ignore_suspend && !enable)
12162306a36Sopenharmony_ci		skl->supend_active--;
12262306a36Sopenharmony_ci}
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ciint skl_pcm_host_dma_prepare(struct device *dev, struct skl_pipe_params *params)
12562306a36Sopenharmony_ci{
12662306a36Sopenharmony_ci	struct hdac_bus *bus = dev_get_drvdata(dev);
12762306a36Sopenharmony_ci	struct skl_dev *skl = bus_to_skl(bus);
12862306a36Sopenharmony_ci	unsigned int format_val;
12962306a36Sopenharmony_ci	struct hdac_stream *hstream;
13062306a36Sopenharmony_ci	struct hdac_ext_stream *stream;
13162306a36Sopenharmony_ci	int err;
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	hstream = snd_hdac_get_stream(bus, params->stream,
13462306a36Sopenharmony_ci					params->host_dma_id + 1);
13562306a36Sopenharmony_ci	if (!hstream)
13662306a36Sopenharmony_ci		return -EINVAL;
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci	stream = stream_to_hdac_ext_stream(hstream);
13962306a36Sopenharmony_ci	snd_hdac_ext_stream_decouple(bus, stream, true);
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci	format_val = snd_hdac_calc_stream_format(params->s_freq,
14262306a36Sopenharmony_ci			params->ch, params->format, params->host_bps, 0);
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci	dev_dbg(dev, "format_val=%d, rate=%d, ch=%d, format=%d\n",
14562306a36Sopenharmony_ci		format_val, params->s_freq, params->ch, params->format);
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci	snd_hdac_stream_reset(hdac_stream(stream));
14862306a36Sopenharmony_ci	err = snd_hdac_stream_set_params(hdac_stream(stream), format_val);
14962306a36Sopenharmony_ci	if (err < 0)
15062306a36Sopenharmony_ci		return err;
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci	/*
15362306a36Sopenharmony_ci	 * The recommended SDxFMT programming sequence for BXT
15462306a36Sopenharmony_ci	 * platforms is to couple the stream before writing the format
15562306a36Sopenharmony_ci	 */
15662306a36Sopenharmony_ci	if (HDA_CONTROLLER_IS_APL(skl->pci)) {
15762306a36Sopenharmony_ci		snd_hdac_ext_stream_decouple(bus, stream, false);
15862306a36Sopenharmony_ci		err = snd_hdac_stream_setup(hdac_stream(stream));
15962306a36Sopenharmony_ci		snd_hdac_ext_stream_decouple(bus, stream, true);
16062306a36Sopenharmony_ci	} else {
16162306a36Sopenharmony_ci		err = snd_hdac_stream_setup(hdac_stream(stream));
16262306a36Sopenharmony_ci	}
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci	if (err < 0)
16562306a36Sopenharmony_ci		return err;
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci	hdac_stream(stream)->prepared = 1;
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci	return 0;
17062306a36Sopenharmony_ci}
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ciint skl_pcm_link_dma_prepare(struct device *dev, struct skl_pipe_params *params)
17362306a36Sopenharmony_ci{
17462306a36Sopenharmony_ci	struct hdac_bus *bus = dev_get_drvdata(dev);
17562306a36Sopenharmony_ci	unsigned int format_val;
17662306a36Sopenharmony_ci	struct hdac_stream *hstream;
17762306a36Sopenharmony_ci	struct hdac_ext_stream *stream;
17862306a36Sopenharmony_ci	struct hdac_ext_link *link;
17962306a36Sopenharmony_ci	unsigned char stream_tag;
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci	hstream = snd_hdac_get_stream(bus, params->stream,
18262306a36Sopenharmony_ci					params->link_dma_id + 1);
18362306a36Sopenharmony_ci	if (!hstream)
18462306a36Sopenharmony_ci		return -EINVAL;
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ci	stream = stream_to_hdac_ext_stream(hstream);
18762306a36Sopenharmony_ci	snd_hdac_ext_stream_decouple(bus, stream, true);
18862306a36Sopenharmony_ci	format_val = snd_hdac_calc_stream_format(params->s_freq, params->ch,
18962306a36Sopenharmony_ci					params->format, params->link_bps, 0);
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci	dev_dbg(dev, "format_val=%d, rate=%d, ch=%d, format=%d\n",
19262306a36Sopenharmony_ci		format_val, params->s_freq, params->ch, params->format);
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci	snd_hdac_ext_stream_reset(stream);
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci	snd_hdac_ext_stream_setup(stream, format_val);
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci	stream_tag = hstream->stream_tag;
19962306a36Sopenharmony_ci	if (stream->hstream.direction == SNDRV_PCM_STREAM_PLAYBACK) {
20062306a36Sopenharmony_ci		list_for_each_entry(link, &bus->hlink_list, list) {
20162306a36Sopenharmony_ci			if (link->index == params->link_index)
20262306a36Sopenharmony_ci				snd_hdac_ext_bus_link_set_stream_id(link,
20362306a36Sopenharmony_ci								    stream_tag);
20462306a36Sopenharmony_ci		}
20562306a36Sopenharmony_ci	}
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ci	stream->link_prepared = 1;
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci	return 0;
21062306a36Sopenharmony_ci}
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_cistatic int skl_pcm_open(struct snd_pcm_substream *substream,
21362306a36Sopenharmony_ci		struct snd_soc_dai *dai)
21462306a36Sopenharmony_ci{
21562306a36Sopenharmony_ci	struct hdac_bus *bus = dev_get_drvdata(dai->dev);
21662306a36Sopenharmony_ci	struct hdac_ext_stream *stream;
21762306a36Sopenharmony_ci	struct snd_pcm_runtime *runtime = substream->runtime;
21862306a36Sopenharmony_ci	struct skl_dma_params *dma_params;
21962306a36Sopenharmony_ci	struct skl_dev *skl = get_skl_ctx(dai->dev);
22062306a36Sopenharmony_ci	struct skl_module_cfg *mconfig;
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci	dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci	stream = snd_hdac_ext_stream_assign(bus, substream,
22562306a36Sopenharmony_ci					skl_get_host_stream_type(bus));
22662306a36Sopenharmony_ci	if (stream == NULL)
22762306a36Sopenharmony_ci		return -EBUSY;
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci	skl_set_pcm_constrains(bus, runtime);
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ci	/*
23262306a36Sopenharmony_ci	 * disable WALLCLOCK timestamps for capture streams
23362306a36Sopenharmony_ci	 * until we figure out how to handle digital inputs
23462306a36Sopenharmony_ci	 */
23562306a36Sopenharmony_ci	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
23662306a36Sopenharmony_ci		runtime->hw.info &= ~SNDRV_PCM_INFO_HAS_WALL_CLOCK; /* legacy */
23762306a36Sopenharmony_ci		runtime->hw.info &= ~SNDRV_PCM_INFO_HAS_LINK_ATIME;
23862306a36Sopenharmony_ci	}
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci	runtime->private_data = stream;
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_ci	dma_params = kzalloc(sizeof(*dma_params), GFP_KERNEL);
24362306a36Sopenharmony_ci	if (!dma_params)
24462306a36Sopenharmony_ci		return -ENOMEM;
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci	dma_params->stream_tag = hdac_stream(stream)->stream_tag;
24762306a36Sopenharmony_ci	snd_soc_dai_set_dma_data(dai, substream, dma_params);
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci	dev_dbg(dai->dev, "stream tag set in dma params=%d\n",
25062306a36Sopenharmony_ci				 dma_params->stream_tag);
25162306a36Sopenharmony_ci	skl_set_suspend_active(substream, dai, true);
25262306a36Sopenharmony_ci	snd_pcm_set_sync(substream);
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci	mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream);
25562306a36Sopenharmony_ci	if (!mconfig) {
25662306a36Sopenharmony_ci		kfree(dma_params);
25762306a36Sopenharmony_ci		return -EINVAL;
25862306a36Sopenharmony_ci	}
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_ci	skl_tplg_d0i3_get(skl, mconfig->d0i3_caps);
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci	return 0;
26362306a36Sopenharmony_ci}
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_cistatic int skl_pcm_prepare(struct snd_pcm_substream *substream,
26662306a36Sopenharmony_ci		struct snd_soc_dai *dai)
26762306a36Sopenharmony_ci{
26862306a36Sopenharmony_ci	struct skl_dev *skl = get_skl_ctx(dai->dev);
26962306a36Sopenharmony_ci	struct skl_module_cfg *mconfig;
27062306a36Sopenharmony_ci	int ret;
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci	dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci	mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream);
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci	/*
27762306a36Sopenharmony_ci	 * In case of XRUN recovery or in the case when the application
27862306a36Sopenharmony_ci	 * calls prepare another time, reset the FW pipe to clean state
27962306a36Sopenharmony_ci	 */
28062306a36Sopenharmony_ci	if (mconfig &&
28162306a36Sopenharmony_ci		(substream->runtime->state == SNDRV_PCM_STATE_XRUN ||
28262306a36Sopenharmony_ci		 mconfig->pipe->state == SKL_PIPE_CREATED ||
28362306a36Sopenharmony_ci		 mconfig->pipe->state == SKL_PIPE_PAUSED)) {
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci		ret = skl_reset_pipe(skl, mconfig->pipe);
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci		if (ret < 0)
28862306a36Sopenharmony_ci			return ret;
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci		ret = skl_pcm_host_dma_prepare(dai->dev,
29162306a36Sopenharmony_ci					mconfig->pipe->p_params);
29262306a36Sopenharmony_ci		if (ret < 0)
29362306a36Sopenharmony_ci			return ret;
29462306a36Sopenharmony_ci	}
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci	return 0;
29762306a36Sopenharmony_ci}
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_cistatic int skl_pcm_hw_params(struct snd_pcm_substream *substream,
30062306a36Sopenharmony_ci				struct snd_pcm_hw_params *params,
30162306a36Sopenharmony_ci				struct snd_soc_dai *dai)
30262306a36Sopenharmony_ci{
30362306a36Sopenharmony_ci	struct hdac_bus *bus = dev_get_drvdata(dai->dev);
30462306a36Sopenharmony_ci	struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
30562306a36Sopenharmony_ci	struct snd_pcm_runtime *runtime = substream->runtime;
30662306a36Sopenharmony_ci	struct skl_pipe_params p_params = {0};
30762306a36Sopenharmony_ci	struct skl_module_cfg *m_cfg;
30862306a36Sopenharmony_ci	int ret, dma_id;
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_ci	dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
31162306a36Sopenharmony_ci	ret = skl_substream_alloc_pages(bus, substream,
31262306a36Sopenharmony_ci					  params_buffer_bytes(params));
31362306a36Sopenharmony_ci	if (ret < 0)
31462306a36Sopenharmony_ci		return ret;
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_ci	dev_dbg(dai->dev, "format_val, rate=%d, ch=%d, format=%d\n",
31762306a36Sopenharmony_ci			runtime->rate, runtime->channels, runtime->format);
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci	dma_id = hdac_stream(stream)->stream_tag - 1;
32062306a36Sopenharmony_ci	dev_dbg(dai->dev, "dma_id=%d\n", dma_id);
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci	p_params.s_fmt = snd_pcm_format_width(params_format(params));
32362306a36Sopenharmony_ci	p_params.s_cont = snd_pcm_format_physical_width(params_format(params));
32462306a36Sopenharmony_ci	p_params.ch = params_channels(params);
32562306a36Sopenharmony_ci	p_params.s_freq = params_rate(params);
32662306a36Sopenharmony_ci	p_params.host_dma_id = dma_id;
32762306a36Sopenharmony_ci	p_params.stream = substream->stream;
32862306a36Sopenharmony_ci	p_params.format = params_format(params);
32962306a36Sopenharmony_ci	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
33062306a36Sopenharmony_ci		p_params.host_bps = dai->driver->playback.sig_bits;
33162306a36Sopenharmony_ci	else
33262306a36Sopenharmony_ci		p_params.host_bps = dai->driver->capture.sig_bits;
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci	m_cfg = skl_tplg_fe_get_cpr_module(dai, p_params.stream);
33662306a36Sopenharmony_ci	if (m_cfg)
33762306a36Sopenharmony_ci		skl_tplg_update_pipe_params(dai->dev, m_cfg, &p_params);
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_ci	return 0;
34062306a36Sopenharmony_ci}
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_cistatic void skl_pcm_close(struct snd_pcm_substream *substream,
34362306a36Sopenharmony_ci		struct snd_soc_dai *dai)
34462306a36Sopenharmony_ci{
34562306a36Sopenharmony_ci	struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
34662306a36Sopenharmony_ci	struct hdac_bus *bus = dev_get_drvdata(dai->dev);
34762306a36Sopenharmony_ci	struct skl_dma_params *dma_params = NULL;
34862306a36Sopenharmony_ci	struct skl_dev *skl = bus_to_skl(bus);
34962306a36Sopenharmony_ci	struct skl_module_cfg *mconfig;
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_ci	dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_ci	snd_hdac_ext_stream_release(stream, skl_get_host_stream_type(bus));
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci	dma_params = snd_soc_dai_get_dma_data(dai, substream);
35662306a36Sopenharmony_ci	/*
35762306a36Sopenharmony_ci	 * now we should set this to NULL as we are freeing by the
35862306a36Sopenharmony_ci	 * dma_params
35962306a36Sopenharmony_ci	 */
36062306a36Sopenharmony_ci	snd_soc_dai_set_dma_data(dai, substream, NULL);
36162306a36Sopenharmony_ci	skl_set_suspend_active(substream, dai, false);
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci	/*
36462306a36Sopenharmony_ci	 * check if close is for "Reference Pin" and set back the
36562306a36Sopenharmony_ci	 * CGCTL.MISCBDCGE if disabled by driver
36662306a36Sopenharmony_ci	 */
36762306a36Sopenharmony_ci	if (!strncmp(dai->name, "Reference Pin", 13) &&
36862306a36Sopenharmony_ci			skl->miscbdcg_disabled) {
36962306a36Sopenharmony_ci		skl->enable_miscbdcge(dai->dev, true);
37062306a36Sopenharmony_ci		skl->miscbdcg_disabled = false;
37162306a36Sopenharmony_ci	}
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_ci	mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream);
37462306a36Sopenharmony_ci	if (mconfig)
37562306a36Sopenharmony_ci		skl_tplg_d0i3_put(skl, mconfig->d0i3_caps);
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci	kfree(dma_params);
37862306a36Sopenharmony_ci}
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_cistatic int skl_pcm_hw_free(struct snd_pcm_substream *substream,
38162306a36Sopenharmony_ci		struct snd_soc_dai *dai)
38262306a36Sopenharmony_ci{
38362306a36Sopenharmony_ci	struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
38462306a36Sopenharmony_ci	struct skl_dev *skl = get_skl_ctx(dai->dev);
38562306a36Sopenharmony_ci	struct skl_module_cfg *mconfig;
38662306a36Sopenharmony_ci	int ret;
38762306a36Sopenharmony_ci
38862306a36Sopenharmony_ci	dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ci	mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream);
39162306a36Sopenharmony_ci
39262306a36Sopenharmony_ci	if (mconfig) {
39362306a36Sopenharmony_ci		ret = skl_reset_pipe(skl, mconfig->pipe);
39462306a36Sopenharmony_ci		if (ret < 0)
39562306a36Sopenharmony_ci			dev_err(dai->dev, "%s:Reset failed ret =%d",
39662306a36Sopenharmony_ci						__func__, ret);
39762306a36Sopenharmony_ci	}
39862306a36Sopenharmony_ci
39962306a36Sopenharmony_ci	snd_hdac_stream_cleanup(hdac_stream(stream));
40062306a36Sopenharmony_ci	hdac_stream(stream)->prepared = 0;
40162306a36Sopenharmony_ci
40262306a36Sopenharmony_ci	return 0;
40362306a36Sopenharmony_ci}
40462306a36Sopenharmony_ci
40562306a36Sopenharmony_cistatic int skl_be_hw_params(struct snd_pcm_substream *substream,
40662306a36Sopenharmony_ci				struct snd_pcm_hw_params *params,
40762306a36Sopenharmony_ci				struct snd_soc_dai *dai)
40862306a36Sopenharmony_ci{
40962306a36Sopenharmony_ci	struct skl_pipe_params p_params = {0};
41062306a36Sopenharmony_ci
41162306a36Sopenharmony_ci	p_params.s_fmt = snd_pcm_format_width(params_format(params));
41262306a36Sopenharmony_ci	p_params.s_cont = snd_pcm_format_physical_width(params_format(params));
41362306a36Sopenharmony_ci	p_params.ch = params_channels(params);
41462306a36Sopenharmony_ci	p_params.s_freq = params_rate(params);
41562306a36Sopenharmony_ci	p_params.stream = substream->stream;
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_ci	return skl_tplg_be_update_params(dai, &p_params);
41862306a36Sopenharmony_ci}
41962306a36Sopenharmony_ci
42062306a36Sopenharmony_cistatic int skl_decoupled_trigger(struct snd_pcm_substream *substream,
42162306a36Sopenharmony_ci		int cmd)
42262306a36Sopenharmony_ci{
42362306a36Sopenharmony_ci	struct hdac_bus *bus = get_bus_ctx(substream);
42462306a36Sopenharmony_ci	struct hdac_ext_stream *stream;
42562306a36Sopenharmony_ci	int start;
42662306a36Sopenharmony_ci	unsigned long cookie;
42762306a36Sopenharmony_ci	struct hdac_stream *hstr;
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_ci	stream = get_hdac_ext_stream(substream);
43062306a36Sopenharmony_ci	hstr = hdac_stream(stream);
43162306a36Sopenharmony_ci
43262306a36Sopenharmony_ci	if (!hstr->prepared)
43362306a36Sopenharmony_ci		return -EPIPE;
43462306a36Sopenharmony_ci
43562306a36Sopenharmony_ci	switch (cmd) {
43662306a36Sopenharmony_ci	case SNDRV_PCM_TRIGGER_START:
43762306a36Sopenharmony_ci	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
43862306a36Sopenharmony_ci	case SNDRV_PCM_TRIGGER_RESUME:
43962306a36Sopenharmony_ci		start = 1;
44062306a36Sopenharmony_ci		break;
44162306a36Sopenharmony_ci
44262306a36Sopenharmony_ci	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
44362306a36Sopenharmony_ci	case SNDRV_PCM_TRIGGER_SUSPEND:
44462306a36Sopenharmony_ci	case SNDRV_PCM_TRIGGER_STOP:
44562306a36Sopenharmony_ci		start = 0;
44662306a36Sopenharmony_ci		break;
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_ci	default:
44962306a36Sopenharmony_ci		return -EINVAL;
45062306a36Sopenharmony_ci	}
45162306a36Sopenharmony_ci
45262306a36Sopenharmony_ci	spin_lock_irqsave(&bus->reg_lock, cookie);
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_ci	if (start) {
45562306a36Sopenharmony_ci		snd_hdac_stream_start(hdac_stream(stream));
45662306a36Sopenharmony_ci		snd_hdac_stream_timecounter_init(hstr, 0);
45762306a36Sopenharmony_ci	} else {
45862306a36Sopenharmony_ci		snd_hdac_stream_stop(hdac_stream(stream));
45962306a36Sopenharmony_ci	}
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_ci	spin_unlock_irqrestore(&bus->reg_lock, cookie);
46262306a36Sopenharmony_ci
46362306a36Sopenharmony_ci	return 0;
46462306a36Sopenharmony_ci}
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_cistatic int skl_pcm_trigger(struct snd_pcm_substream *substream, int cmd,
46762306a36Sopenharmony_ci		struct snd_soc_dai *dai)
46862306a36Sopenharmony_ci{
46962306a36Sopenharmony_ci	struct skl_dev *skl = get_skl_ctx(dai->dev);
47062306a36Sopenharmony_ci	struct skl_module_cfg *mconfig;
47162306a36Sopenharmony_ci	struct hdac_bus *bus = get_bus_ctx(substream);
47262306a36Sopenharmony_ci	struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
47362306a36Sopenharmony_ci	struct hdac_stream *hstream = hdac_stream(stream);
47462306a36Sopenharmony_ci	struct snd_soc_dapm_widget *w;
47562306a36Sopenharmony_ci	int ret;
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_ci	mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream);
47862306a36Sopenharmony_ci	if (!mconfig)
47962306a36Sopenharmony_ci		return -EIO;
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_ci	w = snd_soc_dai_get_widget(dai, substream->stream);
48262306a36Sopenharmony_ci
48362306a36Sopenharmony_ci	switch (cmd) {
48462306a36Sopenharmony_ci	case SNDRV_PCM_TRIGGER_RESUME:
48562306a36Sopenharmony_ci		if (!w->ignore_suspend) {
48662306a36Sopenharmony_ci			/*
48762306a36Sopenharmony_ci			 * enable DMA Resume enable bit for the stream, set the
48862306a36Sopenharmony_ci			 * dpib & lpib position to resume before starting the
48962306a36Sopenharmony_ci			 * DMA
49062306a36Sopenharmony_ci			 */
49162306a36Sopenharmony_ci			snd_hdac_stream_drsm_enable(bus, true, hstream->index);
49262306a36Sopenharmony_ci			snd_hdac_stream_set_dpibr(bus, hstream, hstream->lpib);
49362306a36Sopenharmony_ci			snd_hdac_stream_set_lpib(hstream, hstream->lpib);
49462306a36Sopenharmony_ci		}
49562306a36Sopenharmony_ci		fallthrough;
49662306a36Sopenharmony_ci
49762306a36Sopenharmony_ci	case SNDRV_PCM_TRIGGER_START:
49862306a36Sopenharmony_ci	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
49962306a36Sopenharmony_ci		/*
50062306a36Sopenharmony_ci		 * Start HOST DMA and Start FE Pipe.This is to make sure that
50162306a36Sopenharmony_ci		 * there are no underrun/overrun in the case when the FE
50262306a36Sopenharmony_ci		 * pipeline is started but there is a delay in starting the
50362306a36Sopenharmony_ci		 * DMA channel on the host.
50462306a36Sopenharmony_ci		 */
50562306a36Sopenharmony_ci		ret = skl_decoupled_trigger(substream, cmd);
50662306a36Sopenharmony_ci		if (ret < 0)
50762306a36Sopenharmony_ci			return ret;
50862306a36Sopenharmony_ci		return skl_run_pipe(skl, mconfig->pipe);
50962306a36Sopenharmony_ci
51062306a36Sopenharmony_ci	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
51162306a36Sopenharmony_ci	case SNDRV_PCM_TRIGGER_SUSPEND:
51262306a36Sopenharmony_ci	case SNDRV_PCM_TRIGGER_STOP:
51362306a36Sopenharmony_ci		/*
51462306a36Sopenharmony_ci		 * Stop FE Pipe first and stop DMA. This is to make sure that
51562306a36Sopenharmony_ci		 * there are no underrun/overrun in the case if there is a delay
51662306a36Sopenharmony_ci		 * between the two operations.
51762306a36Sopenharmony_ci		 */
51862306a36Sopenharmony_ci		ret = skl_stop_pipe(skl, mconfig->pipe);
51962306a36Sopenharmony_ci		if (ret < 0)
52062306a36Sopenharmony_ci			return ret;
52162306a36Sopenharmony_ci
52262306a36Sopenharmony_ci		ret = skl_decoupled_trigger(substream, cmd);
52362306a36Sopenharmony_ci		if ((cmd == SNDRV_PCM_TRIGGER_SUSPEND) && !w->ignore_suspend) {
52462306a36Sopenharmony_ci			/* save the dpib and lpib positions */
52562306a36Sopenharmony_ci			hstream->dpib = readl(bus->remap_addr +
52662306a36Sopenharmony_ci					AZX_REG_VS_SDXDPIB_XBASE +
52762306a36Sopenharmony_ci					(AZX_REG_VS_SDXDPIB_XINTERVAL *
52862306a36Sopenharmony_ci					hstream->index));
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_ci			hstream->lpib = snd_hdac_stream_get_pos_lpib(hstream);
53162306a36Sopenharmony_ci
53262306a36Sopenharmony_ci			snd_hdac_ext_stream_decouple(bus, stream, false);
53362306a36Sopenharmony_ci		}
53462306a36Sopenharmony_ci		break;
53562306a36Sopenharmony_ci
53662306a36Sopenharmony_ci	default:
53762306a36Sopenharmony_ci		return -EINVAL;
53862306a36Sopenharmony_ci	}
53962306a36Sopenharmony_ci
54062306a36Sopenharmony_ci	return 0;
54162306a36Sopenharmony_ci}
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_ci
54462306a36Sopenharmony_cistatic int skl_link_hw_params(struct snd_pcm_substream *substream,
54562306a36Sopenharmony_ci				struct snd_pcm_hw_params *params,
54662306a36Sopenharmony_ci				struct snd_soc_dai *dai)
54762306a36Sopenharmony_ci{
54862306a36Sopenharmony_ci	struct hdac_bus *bus = dev_get_drvdata(dai->dev);
54962306a36Sopenharmony_ci	struct hdac_ext_stream *link_dev;
55062306a36Sopenharmony_ci	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
55162306a36Sopenharmony_ci	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
55262306a36Sopenharmony_ci	struct skl_pipe_params p_params = {0};
55362306a36Sopenharmony_ci	struct hdac_ext_link *link;
55462306a36Sopenharmony_ci	int stream_tag;
55562306a36Sopenharmony_ci
55662306a36Sopenharmony_ci	link_dev = snd_hdac_ext_stream_assign(bus, substream,
55762306a36Sopenharmony_ci					HDAC_EXT_STREAM_TYPE_LINK);
55862306a36Sopenharmony_ci	if (!link_dev)
55962306a36Sopenharmony_ci		return -EBUSY;
56062306a36Sopenharmony_ci
56162306a36Sopenharmony_ci	snd_soc_dai_set_dma_data(dai, substream, (void *)link_dev);
56262306a36Sopenharmony_ci
56362306a36Sopenharmony_ci	link = snd_hdac_ext_bus_get_hlink_by_name(bus, codec_dai->component->name);
56462306a36Sopenharmony_ci	if (!link)
56562306a36Sopenharmony_ci		return -EINVAL;
56662306a36Sopenharmony_ci
56762306a36Sopenharmony_ci	stream_tag = hdac_stream(link_dev)->stream_tag;
56862306a36Sopenharmony_ci
56962306a36Sopenharmony_ci	/* set the hdac_stream in the codec dai */
57062306a36Sopenharmony_ci	snd_soc_dai_set_stream(codec_dai, hdac_stream(link_dev), substream->stream);
57162306a36Sopenharmony_ci
57262306a36Sopenharmony_ci	p_params.s_fmt = snd_pcm_format_width(params_format(params));
57362306a36Sopenharmony_ci	p_params.s_cont = snd_pcm_format_physical_width(params_format(params));
57462306a36Sopenharmony_ci	p_params.ch = params_channels(params);
57562306a36Sopenharmony_ci	p_params.s_freq = params_rate(params);
57662306a36Sopenharmony_ci	p_params.stream = substream->stream;
57762306a36Sopenharmony_ci	p_params.link_dma_id = stream_tag - 1;
57862306a36Sopenharmony_ci	p_params.link_index = link->index;
57962306a36Sopenharmony_ci	p_params.format = params_format(params);
58062306a36Sopenharmony_ci
58162306a36Sopenharmony_ci	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
58262306a36Sopenharmony_ci		p_params.link_bps = codec_dai->driver->playback.sig_bits;
58362306a36Sopenharmony_ci	else
58462306a36Sopenharmony_ci		p_params.link_bps = codec_dai->driver->capture.sig_bits;
58562306a36Sopenharmony_ci
58662306a36Sopenharmony_ci	return skl_tplg_be_update_params(dai, &p_params);
58762306a36Sopenharmony_ci}
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_cistatic int skl_link_pcm_prepare(struct snd_pcm_substream *substream,
59062306a36Sopenharmony_ci		struct snd_soc_dai *dai)
59162306a36Sopenharmony_ci{
59262306a36Sopenharmony_ci	struct skl_dev *skl = get_skl_ctx(dai->dev);
59362306a36Sopenharmony_ci	struct skl_module_cfg *mconfig = NULL;
59462306a36Sopenharmony_ci
59562306a36Sopenharmony_ci	/* In case of XRUN recovery, reset the FW pipe to clean state */
59662306a36Sopenharmony_ci	mconfig = skl_tplg_be_get_cpr_module(dai, substream->stream);
59762306a36Sopenharmony_ci	if (mconfig && !mconfig->pipe->passthru &&
59862306a36Sopenharmony_ci		(substream->runtime->state == SNDRV_PCM_STATE_XRUN))
59962306a36Sopenharmony_ci		skl_reset_pipe(skl, mconfig->pipe);
60062306a36Sopenharmony_ci
60162306a36Sopenharmony_ci	return 0;
60262306a36Sopenharmony_ci}
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_cistatic int skl_link_pcm_trigger(struct snd_pcm_substream *substream,
60562306a36Sopenharmony_ci	int cmd, struct snd_soc_dai *dai)
60662306a36Sopenharmony_ci{
60762306a36Sopenharmony_ci	struct hdac_ext_stream *link_dev =
60862306a36Sopenharmony_ci				snd_soc_dai_get_dma_data(dai, substream);
60962306a36Sopenharmony_ci	struct hdac_bus *bus = get_bus_ctx(substream);
61062306a36Sopenharmony_ci	struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
61162306a36Sopenharmony_ci
61262306a36Sopenharmony_ci	dev_dbg(dai->dev, "In %s cmd=%d\n", __func__, cmd);
61362306a36Sopenharmony_ci	switch (cmd) {
61462306a36Sopenharmony_ci	case SNDRV_PCM_TRIGGER_RESUME:
61562306a36Sopenharmony_ci	case SNDRV_PCM_TRIGGER_START:
61662306a36Sopenharmony_ci	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
61762306a36Sopenharmony_ci		snd_hdac_ext_stream_start(link_dev);
61862306a36Sopenharmony_ci		break;
61962306a36Sopenharmony_ci
62062306a36Sopenharmony_ci	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
62162306a36Sopenharmony_ci	case SNDRV_PCM_TRIGGER_SUSPEND:
62262306a36Sopenharmony_ci	case SNDRV_PCM_TRIGGER_STOP:
62362306a36Sopenharmony_ci		snd_hdac_ext_stream_clear(link_dev);
62462306a36Sopenharmony_ci		if (cmd == SNDRV_PCM_TRIGGER_SUSPEND)
62562306a36Sopenharmony_ci			snd_hdac_ext_stream_decouple(bus, stream, false);
62662306a36Sopenharmony_ci		break;
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_ci	default:
62962306a36Sopenharmony_ci		return -EINVAL;
63062306a36Sopenharmony_ci	}
63162306a36Sopenharmony_ci	return 0;
63262306a36Sopenharmony_ci}
63362306a36Sopenharmony_ci
63462306a36Sopenharmony_cistatic int skl_link_hw_free(struct snd_pcm_substream *substream,
63562306a36Sopenharmony_ci		struct snd_soc_dai *dai)
63662306a36Sopenharmony_ci{
63762306a36Sopenharmony_ci	struct hdac_bus *bus = dev_get_drvdata(dai->dev);
63862306a36Sopenharmony_ci	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
63962306a36Sopenharmony_ci	struct hdac_ext_stream *link_dev =
64062306a36Sopenharmony_ci				snd_soc_dai_get_dma_data(dai, substream);
64162306a36Sopenharmony_ci	struct hdac_ext_link *link;
64262306a36Sopenharmony_ci	unsigned char stream_tag;
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_ci	dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
64562306a36Sopenharmony_ci
64662306a36Sopenharmony_ci	link_dev->link_prepared = 0;
64762306a36Sopenharmony_ci
64862306a36Sopenharmony_ci	link = snd_hdac_ext_bus_get_hlink_by_name(bus, asoc_rtd_to_codec(rtd, 0)->component->name);
64962306a36Sopenharmony_ci	if (!link)
65062306a36Sopenharmony_ci		return -EINVAL;
65162306a36Sopenharmony_ci
65262306a36Sopenharmony_ci	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
65362306a36Sopenharmony_ci		stream_tag = hdac_stream(link_dev)->stream_tag;
65462306a36Sopenharmony_ci		snd_hdac_ext_bus_link_clear_stream_id(link, stream_tag);
65562306a36Sopenharmony_ci	}
65662306a36Sopenharmony_ci
65762306a36Sopenharmony_ci	snd_hdac_ext_stream_release(link_dev, HDAC_EXT_STREAM_TYPE_LINK);
65862306a36Sopenharmony_ci	return 0;
65962306a36Sopenharmony_ci}
66062306a36Sopenharmony_ci
66162306a36Sopenharmony_cistatic const struct snd_soc_dai_ops skl_pcm_dai_ops = {
66262306a36Sopenharmony_ci	.startup = skl_pcm_open,
66362306a36Sopenharmony_ci	.shutdown = skl_pcm_close,
66462306a36Sopenharmony_ci	.prepare = skl_pcm_prepare,
66562306a36Sopenharmony_ci	.hw_params = skl_pcm_hw_params,
66662306a36Sopenharmony_ci	.hw_free = skl_pcm_hw_free,
66762306a36Sopenharmony_ci	.trigger = skl_pcm_trigger,
66862306a36Sopenharmony_ci};
66962306a36Sopenharmony_ci
67062306a36Sopenharmony_cistatic const struct snd_soc_dai_ops skl_dmic_dai_ops = {
67162306a36Sopenharmony_ci	.hw_params = skl_be_hw_params,
67262306a36Sopenharmony_ci};
67362306a36Sopenharmony_ci
67462306a36Sopenharmony_cistatic const struct snd_soc_dai_ops skl_be_ssp_dai_ops = {
67562306a36Sopenharmony_ci	.hw_params = skl_be_hw_params,
67662306a36Sopenharmony_ci};
67762306a36Sopenharmony_ci
67862306a36Sopenharmony_cistatic const struct snd_soc_dai_ops skl_link_dai_ops = {
67962306a36Sopenharmony_ci	.prepare = skl_link_pcm_prepare,
68062306a36Sopenharmony_ci	.hw_params = skl_link_hw_params,
68162306a36Sopenharmony_ci	.hw_free = skl_link_hw_free,
68262306a36Sopenharmony_ci	.trigger = skl_link_pcm_trigger,
68362306a36Sopenharmony_ci};
68462306a36Sopenharmony_ci
68562306a36Sopenharmony_cistatic struct snd_soc_dai_driver skl_fe_dai[] = {
68662306a36Sopenharmony_ci{
68762306a36Sopenharmony_ci	.name = "System Pin",
68862306a36Sopenharmony_ci	.ops = &skl_pcm_dai_ops,
68962306a36Sopenharmony_ci	.playback = {
69062306a36Sopenharmony_ci		.stream_name = "System Playback",
69162306a36Sopenharmony_ci		.channels_min = HDA_MONO,
69262306a36Sopenharmony_ci		.channels_max = HDA_STEREO,
69362306a36Sopenharmony_ci		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_8000,
69462306a36Sopenharmony_ci		.formats = SNDRV_PCM_FMTBIT_S16_LE |
69562306a36Sopenharmony_ci			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE,
69662306a36Sopenharmony_ci		.sig_bits = 32,
69762306a36Sopenharmony_ci	},
69862306a36Sopenharmony_ci	.capture = {
69962306a36Sopenharmony_ci		.stream_name = "System Capture",
70062306a36Sopenharmony_ci		.channels_min = HDA_MONO,
70162306a36Sopenharmony_ci		.channels_max = HDA_STEREO,
70262306a36Sopenharmony_ci		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000,
70362306a36Sopenharmony_ci		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
70462306a36Sopenharmony_ci		.sig_bits = 32,
70562306a36Sopenharmony_ci	},
70662306a36Sopenharmony_ci},
70762306a36Sopenharmony_ci{
70862306a36Sopenharmony_ci	.name = "System Pin2",
70962306a36Sopenharmony_ci	.ops = &skl_pcm_dai_ops,
71062306a36Sopenharmony_ci	.playback = {
71162306a36Sopenharmony_ci		.stream_name = "Headset Playback",
71262306a36Sopenharmony_ci		.channels_min = HDA_MONO,
71362306a36Sopenharmony_ci		.channels_max = HDA_STEREO,
71462306a36Sopenharmony_ci		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000 |
71562306a36Sopenharmony_ci			SNDRV_PCM_RATE_8000,
71662306a36Sopenharmony_ci		.formats = SNDRV_PCM_FMTBIT_S16_LE |
71762306a36Sopenharmony_ci			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE,
71862306a36Sopenharmony_ci	},
71962306a36Sopenharmony_ci},
72062306a36Sopenharmony_ci{
72162306a36Sopenharmony_ci	.name = "Echoref Pin",
72262306a36Sopenharmony_ci	.ops = &skl_pcm_dai_ops,
72362306a36Sopenharmony_ci	.capture = {
72462306a36Sopenharmony_ci		.stream_name = "Echoreference Capture",
72562306a36Sopenharmony_ci		.channels_min = HDA_STEREO,
72662306a36Sopenharmony_ci		.channels_max = HDA_STEREO,
72762306a36Sopenharmony_ci		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000 |
72862306a36Sopenharmony_ci			SNDRV_PCM_RATE_8000,
72962306a36Sopenharmony_ci		.formats = SNDRV_PCM_FMTBIT_S16_LE |
73062306a36Sopenharmony_ci			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE,
73162306a36Sopenharmony_ci	},
73262306a36Sopenharmony_ci},
73362306a36Sopenharmony_ci{
73462306a36Sopenharmony_ci	.name = "Reference Pin",
73562306a36Sopenharmony_ci	.ops = &skl_pcm_dai_ops,
73662306a36Sopenharmony_ci	.capture = {
73762306a36Sopenharmony_ci		.stream_name = "Reference Capture",
73862306a36Sopenharmony_ci		.channels_min = HDA_MONO,
73962306a36Sopenharmony_ci		.channels_max = HDA_QUAD,
74062306a36Sopenharmony_ci		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000,
74162306a36Sopenharmony_ci		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
74262306a36Sopenharmony_ci		.sig_bits = 32,
74362306a36Sopenharmony_ci	},
74462306a36Sopenharmony_ci},
74562306a36Sopenharmony_ci{
74662306a36Sopenharmony_ci	.name = "Deepbuffer Pin",
74762306a36Sopenharmony_ci	.ops = &skl_pcm_dai_ops,
74862306a36Sopenharmony_ci	.playback = {
74962306a36Sopenharmony_ci		.stream_name = "Deepbuffer Playback",
75062306a36Sopenharmony_ci		.channels_min = HDA_STEREO,
75162306a36Sopenharmony_ci		.channels_max = HDA_STEREO,
75262306a36Sopenharmony_ci		.rates = SNDRV_PCM_RATE_48000,
75362306a36Sopenharmony_ci		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
75462306a36Sopenharmony_ci		.sig_bits = 32,
75562306a36Sopenharmony_ci	},
75662306a36Sopenharmony_ci},
75762306a36Sopenharmony_ci{
75862306a36Sopenharmony_ci	.name = "LowLatency Pin",
75962306a36Sopenharmony_ci	.ops = &skl_pcm_dai_ops,
76062306a36Sopenharmony_ci	.playback = {
76162306a36Sopenharmony_ci		.stream_name = "Low Latency Playback",
76262306a36Sopenharmony_ci		.channels_min = HDA_STEREO,
76362306a36Sopenharmony_ci		.channels_max = HDA_STEREO,
76462306a36Sopenharmony_ci		.rates = SNDRV_PCM_RATE_48000,
76562306a36Sopenharmony_ci		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
76662306a36Sopenharmony_ci		.sig_bits = 32,
76762306a36Sopenharmony_ci	},
76862306a36Sopenharmony_ci},
76962306a36Sopenharmony_ci{
77062306a36Sopenharmony_ci	.name = "DMIC Pin",
77162306a36Sopenharmony_ci	.ops = &skl_pcm_dai_ops,
77262306a36Sopenharmony_ci	.capture = {
77362306a36Sopenharmony_ci		.stream_name = "DMIC Capture",
77462306a36Sopenharmony_ci		.channels_min = HDA_MONO,
77562306a36Sopenharmony_ci		.channels_max = HDA_QUAD,
77662306a36Sopenharmony_ci		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000,
77762306a36Sopenharmony_ci		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
77862306a36Sopenharmony_ci		.sig_bits = 32,
77962306a36Sopenharmony_ci	},
78062306a36Sopenharmony_ci},
78162306a36Sopenharmony_ci{
78262306a36Sopenharmony_ci	.name = "HDMI1 Pin",
78362306a36Sopenharmony_ci	.ops = &skl_pcm_dai_ops,
78462306a36Sopenharmony_ci	.playback = {
78562306a36Sopenharmony_ci		.stream_name = "HDMI1 Playback",
78662306a36Sopenharmony_ci		.channels_min = HDA_STEREO,
78762306a36Sopenharmony_ci		.channels_max = 8,
78862306a36Sopenharmony_ci		.rates = SNDRV_PCM_RATE_32000 |	SNDRV_PCM_RATE_44100 |
78962306a36Sopenharmony_ci			SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |
79062306a36Sopenharmony_ci			SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |
79162306a36Sopenharmony_ci			SNDRV_PCM_RATE_192000,
79262306a36Sopenharmony_ci		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
79362306a36Sopenharmony_ci			SNDRV_PCM_FMTBIT_S32_LE,
79462306a36Sopenharmony_ci		.sig_bits = 32,
79562306a36Sopenharmony_ci	},
79662306a36Sopenharmony_ci},
79762306a36Sopenharmony_ci{
79862306a36Sopenharmony_ci	.name = "HDMI2 Pin",
79962306a36Sopenharmony_ci	.ops = &skl_pcm_dai_ops,
80062306a36Sopenharmony_ci	.playback = {
80162306a36Sopenharmony_ci		.stream_name = "HDMI2 Playback",
80262306a36Sopenharmony_ci		.channels_min = HDA_STEREO,
80362306a36Sopenharmony_ci		.channels_max = 8,
80462306a36Sopenharmony_ci		.rates = SNDRV_PCM_RATE_32000 |	SNDRV_PCM_RATE_44100 |
80562306a36Sopenharmony_ci			SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |
80662306a36Sopenharmony_ci			SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |
80762306a36Sopenharmony_ci			SNDRV_PCM_RATE_192000,
80862306a36Sopenharmony_ci		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
80962306a36Sopenharmony_ci			SNDRV_PCM_FMTBIT_S32_LE,
81062306a36Sopenharmony_ci		.sig_bits = 32,
81162306a36Sopenharmony_ci	},
81262306a36Sopenharmony_ci},
81362306a36Sopenharmony_ci{
81462306a36Sopenharmony_ci	.name = "HDMI3 Pin",
81562306a36Sopenharmony_ci	.ops = &skl_pcm_dai_ops,
81662306a36Sopenharmony_ci	.playback = {
81762306a36Sopenharmony_ci		.stream_name = "HDMI3 Playback",
81862306a36Sopenharmony_ci		.channels_min = HDA_STEREO,
81962306a36Sopenharmony_ci		.channels_max = 8,
82062306a36Sopenharmony_ci		.rates = SNDRV_PCM_RATE_32000 |	SNDRV_PCM_RATE_44100 |
82162306a36Sopenharmony_ci			SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |
82262306a36Sopenharmony_ci			SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |
82362306a36Sopenharmony_ci			SNDRV_PCM_RATE_192000,
82462306a36Sopenharmony_ci		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
82562306a36Sopenharmony_ci			SNDRV_PCM_FMTBIT_S32_LE,
82662306a36Sopenharmony_ci		.sig_bits = 32,
82762306a36Sopenharmony_ci	},
82862306a36Sopenharmony_ci},
82962306a36Sopenharmony_ci};
83062306a36Sopenharmony_ci
83162306a36Sopenharmony_ci/* BE CPU  Dais */
83262306a36Sopenharmony_cistatic struct snd_soc_dai_driver skl_platform_dai[] = {
83362306a36Sopenharmony_ci{
83462306a36Sopenharmony_ci	.name = "SSP0 Pin",
83562306a36Sopenharmony_ci	.ops = &skl_be_ssp_dai_ops,
83662306a36Sopenharmony_ci	.playback = {
83762306a36Sopenharmony_ci		.stream_name = "ssp0 Tx",
83862306a36Sopenharmony_ci		.channels_min = HDA_STEREO,
83962306a36Sopenharmony_ci		.channels_max = HDA_STEREO,
84062306a36Sopenharmony_ci		.rates = SNDRV_PCM_RATE_48000,
84162306a36Sopenharmony_ci		.formats = SNDRV_PCM_FMTBIT_S16_LE,
84262306a36Sopenharmony_ci	},
84362306a36Sopenharmony_ci	.capture = {
84462306a36Sopenharmony_ci		.stream_name = "ssp0 Rx",
84562306a36Sopenharmony_ci		.channels_min = HDA_STEREO,
84662306a36Sopenharmony_ci		.channels_max = HDA_STEREO,
84762306a36Sopenharmony_ci		.rates = SNDRV_PCM_RATE_48000,
84862306a36Sopenharmony_ci		.formats = SNDRV_PCM_FMTBIT_S16_LE,
84962306a36Sopenharmony_ci	},
85062306a36Sopenharmony_ci},
85162306a36Sopenharmony_ci{
85262306a36Sopenharmony_ci	.name = "SSP1 Pin",
85362306a36Sopenharmony_ci	.ops = &skl_be_ssp_dai_ops,
85462306a36Sopenharmony_ci	.playback = {
85562306a36Sopenharmony_ci		.stream_name = "ssp1 Tx",
85662306a36Sopenharmony_ci		.channels_min = HDA_STEREO,
85762306a36Sopenharmony_ci		.channels_max = HDA_STEREO,
85862306a36Sopenharmony_ci		.rates = SNDRV_PCM_RATE_48000,
85962306a36Sopenharmony_ci		.formats = SNDRV_PCM_FMTBIT_S16_LE,
86062306a36Sopenharmony_ci	},
86162306a36Sopenharmony_ci	.capture = {
86262306a36Sopenharmony_ci		.stream_name = "ssp1 Rx",
86362306a36Sopenharmony_ci		.channels_min = HDA_STEREO,
86462306a36Sopenharmony_ci		.channels_max = HDA_STEREO,
86562306a36Sopenharmony_ci		.rates = SNDRV_PCM_RATE_48000,
86662306a36Sopenharmony_ci		.formats = SNDRV_PCM_FMTBIT_S16_LE,
86762306a36Sopenharmony_ci	},
86862306a36Sopenharmony_ci},
86962306a36Sopenharmony_ci{
87062306a36Sopenharmony_ci	.name = "SSP2 Pin",
87162306a36Sopenharmony_ci	.ops = &skl_be_ssp_dai_ops,
87262306a36Sopenharmony_ci	.playback = {
87362306a36Sopenharmony_ci		.stream_name = "ssp2 Tx",
87462306a36Sopenharmony_ci		.channels_min = HDA_STEREO,
87562306a36Sopenharmony_ci		.channels_max = HDA_STEREO,
87662306a36Sopenharmony_ci		.rates = SNDRV_PCM_RATE_48000,
87762306a36Sopenharmony_ci		.formats = SNDRV_PCM_FMTBIT_S16_LE,
87862306a36Sopenharmony_ci	},
87962306a36Sopenharmony_ci	.capture = {
88062306a36Sopenharmony_ci		.stream_name = "ssp2 Rx",
88162306a36Sopenharmony_ci		.channels_min = HDA_STEREO,
88262306a36Sopenharmony_ci		.channels_max = HDA_STEREO,
88362306a36Sopenharmony_ci		.rates = SNDRV_PCM_RATE_48000,
88462306a36Sopenharmony_ci		.formats = SNDRV_PCM_FMTBIT_S16_LE,
88562306a36Sopenharmony_ci	},
88662306a36Sopenharmony_ci},
88762306a36Sopenharmony_ci{
88862306a36Sopenharmony_ci	.name = "SSP3 Pin",
88962306a36Sopenharmony_ci	.ops = &skl_be_ssp_dai_ops,
89062306a36Sopenharmony_ci	.playback = {
89162306a36Sopenharmony_ci		.stream_name = "ssp3 Tx",
89262306a36Sopenharmony_ci		.channels_min = HDA_STEREO,
89362306a36Sopenharmony_ci		.channels_max = HDA_STEREO,
89462306a36Sopenharmony_ci		.rates = SNDRV_PCM_RATE_48000,
89562306a36Sopenharmony_ci		.formats = SNDRV_PCM_FMTBIT_S16_LE,
89662306a36Sopenharmony_ci	},
89762306a36Sopenharmony_ci	.capture = {
89862306a36Sopenharmony_ci		.stream_name = "ssp3 Rx",
89962306a36Sopenharmony_ci		.channels_min = HDA_STEREO,
90062306a36Sopenharmony_ci		.channels_max = HDA_STEREO,
90162306a36Sopenharmony_ci		.rates = SNDRV_PCM_RATE_48000,
90262306a36Sopenharmony_ci		.formats = SNDRV_PCM_FMTBIT_S16_LE,
90362306a36Sopenharmony_ci	},
90462306a36Sopenharmony_ci},
90562306a36Sopenharmony_ci{
90662306a36Sopenharmony_ci	.name = "SSP4 Pin",
90762306a36Sopenharmony_ci	.ops = &skl_be_ssp_dai_ops,
90862306a36Sopenharmony_ci	.playback = {
90962306a36Sopenharmony_ci		.stream_name = "ssp4 Tx",
91062306a36Sopenharmony_ci		.channels_min = HDA_STEREO,
91162306a36Sopenharmony_ci		.channels_max = HDA_STEREO,
91262306a36Sopenharmony_ci		.rates = SNDRV_PCM_RATE_48000,
91362306a36Sopenharmony_ci		.formats = SNDRV_PCM_FMTBIT_S16_LE,
91462306a36Sopenharmony_ci	},
91562306a36Sopenharmony_ci	.capture = {
91662306a36Sopenharmony_ci		.stream_name = "ssp4 Rx",
91762306a36Sopenharmony_ci		.channels_min = HDA_STEREO,
91862306a36Sopenharmony_ci		.channels_max = HDA_STEREO,
91962306a36Sopenharmony_ci		.rates = SNDRV_PCM_RATE_48000,
92062306a36Sopenharmony_ci		.formats = SNDRV_PCM_FMTBIT_S16_LE,
92162306a36Sopenharmony_ci	},
92262306a36Sopenharmony_ci},
92362306a36Sopenharmony_ci{
92462306a36Sopenharmony_ci	.name = "SSP5 Pin",
92562306a36Sopenharmony_ci	.ops = &skl_be_ssp_dai_ops,
92662306a36Sopenharmony_ci	.playback = {
92762306a36Sopenharmony_ci		.stream_name = "ssp5 Tx",
92862306a36Sopenharmony_ci		.channels_min = HDA_STEREO,
92962306a36Sopenharmony_ci		.channels_max = HDA_STEREO,
93062306a36Sopenharmony_ci		.rates = SNDRV_PCM_RATE_48000,
93162306a36Sopenharmony_ci		.formats = SNDRV_PCM_FMTBIT_S16_LE,
93262306a36Sopenharmony_ci	},
93362306a36Sopenharmony_ci	.capture = {
93462306a36Sopenharmony_ci		.stream_name = "ssp5 Rx",
93562306a36Sopenharmony_ci		.channels_min = HDA_STEREO,
93662306a36Sopenharmony_ci		.channels_max = HDA_STEREO,
93762306a36Sopenharmony_ci		.rates = SNDRV_PCM_RATE_48000,
93862306a36Sopenharmony_ci		.formats = SNDRV_PCM_FMTBIT_S16_LE,
93962306a36Sopenharmony_ci	},
94062306a36Sopenharmony_ci},
94162306a36Sopenharmony_ci{
94262306a36Sopenharmony_ci	.name = "iDisp1 Pin",
94362306a36Sopenharmony_ci	.ops = &skl_link_dai_ops,
94462306a36Sopenharmony_ci	.playback = {
94562306a36Sopenharmony_ci		.stream_name = "iDisp1 Tx",
94662306a36Sopenharmony_ci		.channels_min = HDA_STEREO,
94762306a36Sopenharmony_ci		.channels_max = 8,
94862306a36Sopenharmony_ci		.rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|SNDRV_PCM_RATE_48000,
94962306a36Sopenharmony_ci		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE |
95062306a36Sopenharmony_ci			SNDRV_PCM_FMTBIT_S24_LE,
95162306a36Sopenharmony_ci	},
95262306a36Sopenharmony_ci},
95362306a36Sopenharmony_ci{
95462306a36Sopenharmony_ci	.name = "iDisp2 Pin",
95562306a36Sopenharmony_ci	.ops = &skl_link_dai_ops,
95662306a36Sopenharmony_ci	.playback = {
95762306a36Sopenharmony_ci		.stream_name = "iDisp2 Tx",
95862306a36Sopenharmony_ci		.channels_min = HDA_STEREO,
95962306a36Sopenharmony_ci		.channels_max = 8,
96062306a36Sopenharmony_ci		.rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|
96162306a36Sopenharmony_ci			SNDRV_PCM_RATE_48000,
96262306a36Sopenharmony_ci		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE |
96362306a36Sopenharmony_ci			SNDRV_PCM_FMTBIT_S24_LE,
96462306a36Sopenharmony_ci	},
96562306a36Sopenharmony_ci},
96662306a36Sopenharmony_ci{
96762306a36Sopenharmony_ci	.name = "iDisp3 Pin",
96862306a36Sopenharmony_ci	.ops = &skl_link_dai_ops,
96962306a36Sopenharmony_ci	.playback = {
97062306a36Sopenharmony_ci		.stream_name = "iDisp3 Tx",
97162306a36Sopenharmony_ci		.channels_min = HDA_STEREO,
97262306a36Sopenharmony_ci		.channels_max = 8,
97362306a36Sopenharmony_ci		.rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|
97462306a36Sopenharmony_ci			SNDRV_PCM_RATE_48000,
97562306a36Sopenharmony_ci		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE |
97662306a36Sopenharmony_ci			SNDRV_PCM_FMTBIT_S24_LE,
97762306a36Sopenharmony_ci	},
97862306a36Sopenharmony_ci},
97962306a36Sopenharmony_ci{
98062306a36Sopenharmony_ci	.name = "DMIC01 Pin",
98162306a36Sopenharmony_ci	.ops = &skl_dmic_dai_ops,
98262306a36Sopenharmony_ci	.capture = {
98362306a36Sopenharmony_ci		.stream_name = "DMIC01 Rx",
98462306a36Sopenharmony_ci		.channels_min = HDA_MONO,
98562306a36Sopenharmony_ci		.channels_max = HDA_QUAD,
98662306a36Sopenharmony_ci		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000,
98762306a36Sopenharmony_ci		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
98862306a36Sopenharmony_ci	},
98962306a36Sopenharmony_ci},
99062306a36Sopenharmony_ci{
99162306a36Sopenharmony_ci	.name = "DMIC16k Pin",
99262306a36Sopenharmony_ci	.ops = &skl_dmic_dai_ops,
99362306a36Sopenharmony_ci	.capture = {
99462306a36Sopenharmony_ci		.stream_name = "DMIC16k Rx",
99562306a36Sopenharmony_ci		.channels_min = HDA_MONO,
99662306a36Sopenharmony_ci		.channels_max = HDA_QUAD,
99762306a36Sopenharmony_ci		.rates = SNDRV_PCM_RATE_16000,
99862306a36Sopenharmony_ci		.formats = SNDRV_PCM_FMTBIT_S16_LE,
99962306a36Sopenharmony_ci	},
100062306a36Sopenharmony_ci},
100162306a36Sopenharmony_ci{
100262306a36Sopenharmony_ci	.name = "Analog CPU DAI",
100362306a36Sopenharmony_ci	.ops = &skl_link_dai_ops,
100462306a36Sopenharmony_ci	.playback = {
100562306a36Sopenharmony_ci		.stream_name = "Analog CPU Playback",
100662306a36Sopenharmony_ci		.channels_min = HDA_MONO,
100762306a36Sopenharmony_ci		.channels_max = HDA_MAX,
100862306a36Sopenharmony_ci		.rates = SNDRV_PCM_RATE_8000_192000,
100962306a36Sopenharmony_ci		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
101062306a36Sopenharmony_ci			SNDRV_PCM_FMTBIT_S32_LE,
101162306a36Sopenharmony_ci	},
101262306a36Sopenharmony_ci	.capture = {
101362306a36Sopenharmony_ci		.stream_name = "Analog CPU Capture",
101462306a36Sopenharmony_ci		.channels_min = HDA_MONO,
101562306a36Sopenharmony_ci		.channels_max = HDA_MAX,
101662306a36Sopenharmony_ci		.rates = SNDRV_PCM_RATE_8000_192000,
101762306a36Sopenharmony_ci		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
101862306a36Sopenharmony_ci			SNDRV_PCM_FMTBIT_S32_LE,
101962306a36Sopenharmony_ci	},
102062306a36Sopenharmony_ci},
102162306a36Sopenharmony_ci{
102262306a36Sopenharmony_ci	.name = "Alt Analog CPU DAI",
102362306a36Sopenharmony_ci	.ops = &skl_link_dai_ops,
102462306a36Sopenharmony_ci	.playback = {
102562306a36Sopenharmony_ci		.stream_name = "Alt Analog CPU Playback",
102662306a36Sopenharmony_ci		.channels_min = HDA_MONO,
102762306a36Sopenharmony_ci		.channels_max = HDA_MAX,
102862306a36Sopenharmony_ci		.rates = SNDRV_PCM_RATE_8000_192000,
102962306a36Sopenharmony_ci		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
103062306a36Sopenharmony_ci			SNDRV_PCM_FMTBIT_S32_LE,
103162306a36Sopenharmony_ci	},
103262306a36Sopenharmony_ci	.capture = {
103362306a36Sopenharmony_ci		.stream_name = "Alt Analog CPU Capture",
103462306a36Sopenharmony_ci		.channels_min = HDA_MONO,
103562306a36Sopenharmony_ci		.channels_max = HDA_MAX,
103662306a36Sopenharmony_ci		.rates = SNDRV_PCM_RATE_8000_192000,
103762306a36Sopenharmony_ci		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
103862306a36Sopenharmony_ci			SNDRV_PCM_FMTBIT_S32_LE,
103962306a36Sopenharmony_ci	},
104062306a36Sopenharmony_ci},
104162306a36Sopenharmony_ci{
104262306a36Sopenharmony_ci	.name = "Digital CPU DAI",
104362306a36Sopenharmony_ci	.ops = &skl_link_dai_ops,
104462306a36Sopenharmony_ci	.playback = {
104562306a36Sopenharmony_ci		.stream_name = "Digital CPU Playback",
104662306a36Sopenharmony_ci		.channels_min = HDA_MONO,
104762306a36Sopenharmony_ci		.channels_max = HDA_MAX,
104862306a36Sopenharmony_ci		.rates = SNDRV_PCM_RATE_8000_192000,
104962306a36Sopenharmony_ci		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
105062306a36Sopenharmony_ci			SNDRV_PCM_FMTBIT_S32_LE,
105162306a36Sopenharmony_ci	},
105262306a36Sopenharmony_ci	.capture = {
105362306a36Sopenharmony_ci		.stream_name = "Digital CPU Capture",
105462306a36Sopenharmony_ci		.channels_min = HDA_MONO,
105562306a36Sopenharmony_ci		.channels_max = HDA_MAX,
105662306a36Sopenharmony_ci		.rates = SNDRV_PCM_RATE_8000_192000,
105762306a36Sopenharmony_ci		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
105862306a36Sopenharmony_ci			SNDRV_PCM_FMTBIT_S32_LE,
105962306a36Sopenharmony_ci	},
106062306a36Sopenharmony_ci},
106162306a36Sopenharmony_ci};
106262306a36Sopenharmony_ci
106362306a36Sopenharmony_ciint skl_dai_load(struct snd_soc_component *cmp, int index,
106462306a36Sopenharmony_ci			struct snd_soc_dai_driver *dai_drv,
106562306a36Sopenharmony_ci			struct snd_soc_tplg_pcm *pcm, struct snd_soc_dai *dai)
106662306a36Sopenharmony_ci{
106762306a36Sopenharmony_ci	dai_drv->ops = &skl_pcm_dai_ops;
106862306a36Sopenharmony_ci
106962306a36Sopenharmony_ci	return 0;
107062306a36Sopenharmony_ci}
107162306a36Sopenharmony_ci
107262306a36Sopenharmony_cistatic int skl_platform_soc_open(struct snd_soc_component *component,
107362306a36Sopenharmony_ci				 struct snd_pcm_substream *substream)
107462306a36Sopenharmony_ci{
107562306a36Sopenharmony_ci	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
107662306a36Sopenharmony_ci	struct snd_soc_dai_link *dai_link = rtd->dai_link;
107762306a36Sopenharmony_ci
107862306a36Sopenharmony_ci	dev_dbg(asoc_rtd_to_cpu(rtd, 0)->dev, "In %s:%s\n", __func__,
107962306a36Sopenharmony_ci					dai_link->cpus->dai_name);
108062306a36Sopenharmony_ci
108162306a36Sopenharmony_ci	snd_soc_set_runtime_hwparams(substream, &azx_pcm_hw);
108262306a36Sopenharmony_ci
108362306a36Sopenharmony_ci	return 0;
108462306a36Sopenharmony_ci}
108562306a36Sopenharmony_ci
108662306a36Sopenharmony_cistatic int skl_coupled_trigger(struct snd_pcm_substream *substream,
108762306a36Sopenharmony_ci					int cmd)
108862306a36Sopenharmony_ci{
108962306a36Sopenharmony_ci	struct hdac_bus *bus = get_bus_ctx(substream);
109062306a36Sopenharmony_ci	struct hdac_ext_stream *stream;
109162306a36Sopenharmony_ci	struct snd_pcm_substream *s;
109262306a36Sopenharmony_ci	bool start;
109362306a36Sopenharmony_ci	int sbits = 0;
109462306a36Sopenharmony_ci	unsigned long cookie;
109562306a36Sopenharmony_ci	struct hdac_stream *hstr;
109662306a36Sopenharmony_ci
109762306a36Sopenharmony_ci	stream = get_hdac_ext_stream(substream);
109862306a36Sopenharmony_ci	hstr = hdac_stream(stream);
109962306a36Sopenharmony_ci
110062306a36Sopenharmony_ci	dev_dbg(bus->dev, "In %s cmd=%d\n", __func__, cmd);
110162306a36Sopenharmony_ci
110262306a36Sopenharmony_ci	if (!hstr->prepared)
110362306a36Sopenharmony_ci		return -EPIPE;
110462306a36Sopenharmony_ci
110562306a36Sopenharmony_ci	switch (cmd) {
110662306a36Sopenharmony_ci	case SNDRV_PCM_TRIGGER_START:
110762306a36Sopenharmony_ci	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
110862306a36Sopenharmony_ci	case SNDRV_PCM_TRIGGER_RESUME:
110962306a36Sopenharmony_ci		start = true;
111062306a36Sopenharmony_ci		break;
111162306a36Sopenharmony_ci
111262306a36Sopenharmony_ci	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
111362306a36Sopenharmony_ci	case SNDRV_PCM_TRIGGER_SUSPEND:
111462306a36Sopenharmony_ci	case SNDRV_PCM_TRIGGER_STOP:
111562306a36Sopenharmony_ci		start = false;
111662306a36Sopenharmony_ci		break;
111762306a36Sopenharmony_ci
111862306a36Sopenharmony_ci	default:
111962306a36Sopenharmony_ci		return -EINVAL;
112062306a36Sopenharmony_ci	}
112162306a36Sopenharmony_ci
112262306a36Sopenharmony_ci	snd_pcm_group_for_each_entry(s, substream) {
112362306a36Sopenharmony_ci		if (s->pcm->card != substream->pcm->card)
112462306a36Sopenharmony_ci			continue;
112562306a36Sopenharmony_ci		stream = get_hdac_ext_stream(s);
112662306a36Sopenharmony_ci		sbits |= 1 << hdac_stream(stream)->index;
112762306a36Sopenharmony_ci		snd_pcm_trigger_done(s, substream);
112862306a36Sopenharmony_ci	}
112962306a36Sopenharmony_ci
113062306a36Sopenharmony_ci	spin_lock_irqsave(&bus->reg_lock, cookie);
113162306a36Sopenharmony_ci
113262306a36Sopenharmony_ci	/* first, set SYNC bits of corresponding streams */
113362306a36Sopenharmony_ci	snd_hdac_stream_sync_trigger(hstr, true, sbits, AZX_REG_SSYNC);
113462306a36Sopenharmony_ci
113562306a36Sopenharmony_ci	snd_pcm_group_for_each_entry(s, substream) {
113662306a36Sopenharmony_ci		if (s->pcm->card != substream->pcm->card)
113762306a36Sopenharmony_ci			continue;
113862306a36Sopenharmony_ci		stream = get_hdac_ext_stream(s);
113962306a36Sopenharmony_ci		if (start)
114062306a36Sopenharmony_ci			snd_hdac_stream_start(hdac_stream(stream));
114162306a36Sopenharmony_ci		else
114262306a36Sopenharmony_ci			snd_hdac_stream_stop(hdac_stream(stream));
114362306a36Sopenharmony_ci	}
114462306a36Sopenharmony_ci	spin_unlock_irqrestore(&bus->reg_lock, cookie);
114562306a36Sopenharmony_ci
114662306a36Sopenharmony_ci	snd_hdac_stream_sync(hstr, start, sbits);
114762306a36Sopenharmony_ci
114862306a36Sopenharmony_ci	spin_lock_irqsave(&bus->reg_lock, cookie);
114962306a36Sopenharmony_ci
115062306a36Sopenharmony_ci	/* reset SYNC bits */
115162306a36Sopenharmony_ci	snd_hdac_stream_sync_trigger(hstr, false, sbits, AZX_REG_SSYNC);
115262306a36Sopenharmony_ci	if (start)
115362306a36Sopenharmony_ci		snd_hdac_stream_timecounter_init(hstr, sbits);
115462306a36Sopenharmony_ci	spin_unlock_irqrestore(&bus->reg_lock, cookie);
115562306a36Sopenharmony_ci
115662306a36Sopenharmony_ci	return 0;
115762306a36Sopenharmony_ci}
115862306a36Sopenharmony_ci
115962306a36Sopenharmony_cistatic int skl_platform_soc_trigger(struct snd_soc_component *component,
116062306a36Sopenharmony_ci				    struct snd_pcm_substream *substream,
116162306a36Sopenharmony_ci				    int cmd)
116262306a36Sopenharmony_ci{
116362306a36Sopenharmony_ci	struct hdac_bus *bus = get_bus_ctx(substream);
116462306a36Sopenharmony_ci
116562306a36Sopenharmony_ci	if (!bus->ppcap)
116662306a36Sopenharmony_ci		return skl_coupled_trigger(substream, cmd);
116762306a36Sopenharmony_ci
116862306a36Sopenharmony_ci	return 0;
116962306a36Sopenharmony_ci}
117062306a36Sopenharmony_ci
117162306a36Sopenharmony_cistatic snd_pcm_uframes_t skl_platform_soc_pointer(
117262306a36Sopenharmony_ci	struct snd_soc_component *component,
117362306a36Sopenharmony_ci	struct snd_pcm_substream *substream)
117462306a36Sopenharmony_ci{
117562306a36Sopenharmony_ci	struct hdac_ext_stream *hstream = get_hdac_ext_stream(substream);
117662306a36Sopenharmony_ci	struct hdac_bus *bus = get_bus_ctx(substream);
117762306a36Sopenharmony_ci	unsigned int pos;
117862306a36Sopenharmony_ci
117962306a36Sopenharmony_ci	/*
118062306a36Sopenharmony_ci	 * Use DPIB for Playback stream as the periodic DMA Position-in-
118162306a36Sopenharmony_ci	 * Buffer Writes may be scheduled at the same time or later than
118262306a36Sopenharmony_ci	 * the MSI and does not guarantee to reflect the Position of the
118362306a36Sopenharmony_ci	 * last buffer that was transferred. Whereas DPIB register in
118462306a36Sopenharmony_ci	 * HAD space reflects the actual data that is transferred.
118562306a36Sopenharmony_ci	 * Use the position buffer for capture, as DPIB write gets
118662306a36Sopenharmony_ci	 * completed earlier than the actual data written to the DDR.
118762306a36Sopenharmony_ci	 *
118862306a36Sopenharmony_ci	 * For capture stream following workaround is required to fix the
118962306a36Sopenharmony_ci	 * incorrect position reporting.
119062306a36Sopenharmony_ci	 *
119162306a36Sopenharmony_ci	 * 1. Wait for 20us before reading the DMA position in buffer once
119262306a36Sopenharmony_ci	 * the interrupt is generated for stream completion as update happens
119362306a36Sopenharmony_ci	 * on the HDA frame boundary i.e. 20.833uSec.
119462306a36Sopenharmony_ci	 * 2. Read DPIB register to flush the DMA position value. This dummy
119562306a36Sopenharmony_ci	 * read is required to flush DMA position value.
119662306a36Sopenharmony_ci	 * 3. Read the DMA Position-in-Buffer. This value now will be equal to
119762306a36Sopenharmony_ci	 * or greater than period boundary.
119862306a36Sopenharmony_ci	 */
119962306a36Sopenharmony_ci
120062306a36Sopenharmony_ci	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
120162306a36Sopenharmony_ci		pos = readl(bus->remap_addr + AZX_REG_VS_SDXDPIB_XBASE +
120262306a36Sopenharmony_ci				(AZX_REG_VS_SDXDPIB_XINTERVAL *
120362306a36Sopenharmony_ci				hdac_stream(hstream)->index));
120462306a36Sopenharmony_ci	} else {
120562306a36Sopenharmony_ci		udelay(20);
120662306a36Sopenharmony_ci		readl(bus->remap_addr +
120762306a36Sopenharmony_ci				AZX_REG_VS_SDXDPIB_XBASE +
120862306a36Sopenharmony_ci				(AZX_REG_VS_SDXDPIB_XINTERVAL *
120962306a36Sopenharmony_ci				 hdac_stream(hstream)->index));
121062306a36Sopenharmony_ci		pos = snd_hdac_stream_get_pos_posbuf(hdac_stream(hstream));
121162306a36Sopenharmony_ci	}
121262306a36Sopenharmony_ci
121362306a36Sopenharmony_ci	if (pos >= hdac_stream(hstream)->bufsize)
121462306a36Sopenharmony_ci		pos = 0;
121562306a36Sopenharmony_ci
121662306a36Sopenharmony_ci	return bytes_to_frames(substream->runtime, pos);
121762306a36Sopenharmony_ci}
121862306a36Sopenharmony_ci
121962306a36Sopenharmony_cistatic u64 skl_adjust_codec_delay(struct snd_pcm_substream *substream,
122062306a36Sopenharmony_ci				u64 nsec)
122162306a36Sopenharmony_ci{
122262306a36Sopenharmony_ci	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
122362306a36Sopenharmony_ci	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
122462306a36Sopenharmony_ci	u64 codec_frames, codec_nsecs;
122562306a36Sopenharmony_ci
122662306a36Sopenharmony_ci	if (!codec_dai->driver->ops->delay)
122762306a36Sopenharmony_ci		return nsec;
122862306a36Sopenharmony_ci
122962306a36Sopenharmony_ci	codec_frames = codec_dai->driver->ops->delay(substream, codec_dai);
123062306a36Sopenharmony_ci	codec_nsecs = div_u64(codec_frames * 1000000000LL,
123162306a36Sopenharmony_ci			      substream->runtime->rate);
123262306a36Sopenharmony_ci
123362306a36Sopenharmony_ci	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
123462306a36Sopenharmony_ci		return nsec + codec_nsecs;
123562306a36Sopenharmony_ci
123662306a36Sopenharmony_ci	return (nsec > codec_nsecs) ? nsec - codec_nsecs : 0;
123762306a36Sopenharmony_ci}
123862306a36Sopenharmony_ci
123962306a36Sopenharmony_cistatic int skl_platform_soc_get_time_info(
124062306a36Sopenharmony_ci			struct snd_soc_component *component,
124162306a36Sopenharmony_ci			struct snd_pcm_substream *substream,
124262306a36Sopenharmony_ci			struct timespec64 *system_ts, struct timespec64 *audio_ts,
124362306a36Sopenharmony_ci			struct snd_pcm_audio_tstamp_config *audio_tstamp_config,
124462306a36Sopenharmony_ci			struct snd_pcm_audio_tstamp_report *audio_tstamp_report)
124562306a36Sopenharmony_ci{
124662306a36Sopenharmony_ci	struct hdac_ext_stream *sstream = get_hdac_ext_stream(substream);
124762306a36Sopenharmony_ci	struct hdac_stream *hstr = hdac_stream(sstream);
124862306a36Sopenharmony_ci	u64 nsec;
124962306a36Sopenharmony_ci
125062306a36Sopenharmony_ci	if ((substream->runtime->hw.info & SNDRV_PCM_INFO_HAS_LINK_ATIME) &&
125162306a36Sopenharmony_ci		(audio_tstamp_config->type_requested == SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK)) {
125262306a36Sopenharmony_ci
125362306a36Sopenharmony_ci		snd_pcm_gettime(substream->runtime, system_ts);
125462306a36Sopenharmony_ci
125562306a36Sopenharmony_ci		nsec = timecounter_read(&hstr->tc);
125662306a36Sopenharmony_ci		if (audio_tstamp_config->report_delay)
125762306a36Sopenharmony_ci			nsec = skl_adjust_codec_delay(substream, nsec);
125862306a36Sopenharmony_ci
125962306a36Sopenharmony_ci		*audio_ts = ns_to_timespec64(nsec);
126062306a36Sopenharmony_ci
126162306a36Sopenharmony_ci		audio_tstamp_report->actual_type = SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK;
126262306a36Sopenharmony_ci		audio_tstamp_report->accuracy_report = 1; /* rest of struct is valid */
126362306a36Sopenharmony_ci		audio_tstamp_report->accuracy = 42; /* 24MHzWallClk == 42ns resolution */
126462306a36Sopenharmony_ci
126562306a36Sopenharmony_ci	} else {
126662306a36Sopenharmony_ci		audio_tstamp_report->actual_type = SNDRV_PCM_AUDIO_TSTAMP_TYPE_DEFAULT;
126762306a36Sopenharmony_ci	}
126862306a36Sopenharmony_ci
126962306a36Sopenharmony_ci	return 0;
127062306a36Sopenharmony_ci}
127162306a36Sopenharmony_ci
127262306a36Sopenharmony_ci#define MAX_PREALLOC_SIZE	(32 * 1024 * 1024)
127362306a36Sopenharmony_ci
127462306a36Sopenharmony_cistatic int skl_platform_soc_new(struct snd_soc_component *component,
127562306a36Sopenharmony_ci				struct snd_soc_pcm_runtime *rtd)
127662306a36Sopenharmony_ci{
127762306a36Sopenharmony_ci	struct snd_soc_dai *dai = asoc_rtd_to_cpu(rtd, 0);
127862306a36Sopenharmony_ci	struct hdac_bus *bus = dev_get_drvdata(dai->dev);
127962306a36Sopenharmony_ci	struct snd_pcm *pcm = rtd->pcm;
128062306a36Sopenharmony_ci	unsigned int size;
128162306a36Sopenharmony_ci	struct skl_dev *skl = bus_to_skl(bus);
128262306a36Sopenharmony_ci
128362306a36Sopenharmony_ci	if (dai->driver->playback.channels_min ||
128462306a36Sopenharmony_ci		dai->driver->capture.channels_min) {
128562306a36Sopenharmony_ci		/* buffer pre-allocation */
128662306a36Sopenharmony_ci		size = CONFIG_SND_HDA_PREALLOC_SIZE * 1024;
128762306a36Sopenharmony_ci		if (size > MAX_PREALLOC_SIZE)
128862306a36Sopenharmony_ci			size = MAX_PREALLOC_SIZE;
128962306a36Sopenharmony_ci		snd_pcm_set_managed_buffer_all(pcm,
129062306a36Sopenharmony_ci					       SNDRV_DMA_TYPE_DEV_SG,
129162306a36Sopenharmony_ci					       &skl->pci->dev,
129262306a36Sopenharmony_ci					       size, MAX_PREALLOC_SIZE);
129362306a36Sopenharmony_ci	}
129462306a36Sopenharmony_ci
129562306a36Sopenharmony_ci	return 0;
129662306a36Sopenharmony_ci}
129762306a36Sopenharmony_ci
129862306a36Sopenharmony_cistatic int skl_get_module_info(struct skl_dev *skl,
129962306a36Sopenharmony_ci		struct skl_module_cfg *mconfig)
130062306a36Sopenharmony_ci{
130162306a36Sopenharmony_ci	struct skl_module_inst_id *pin_id;
130262306a36Sopenharmony_ci	guid_t *uuid_mod, *uuid_tplg;
130362306a36Sopenharmony_ci	struct skl_module *skl_module;
130462306a36Sopenharmony_ci	struct uuid_module *module;
130562306a36Sopenharmony_ci	int i, ret = -EIO;
130662306a36Sopenharmony_ci
130762306a36Sopenharmony_ci	uuid_mod = (guid_t *)mconfig->guid;
130862306a36Sopenharmony_ci
130962306a36Sopenharmony_ci	if (list_empty(&skl->uuid_list)) {
131062306a36Sopenharmony_ci		dev_err(skl->dev, "Module list is empty\n");
131162306a36Sopenharmony_ci		return -EIO;
131262306a36Sopenharmony_ci	}
131362306a36Sopenharmony_ci
131462306a36Sopenharmony_ci	for (i = 0; i < skl->nr_modules; i++) {
131562306a36Sopenharmony_ci		skl_module = skl->modules[i];
131662306a36Sopenharmony_ci		uuid_tplg = &skl_module->uuid;
131762306a36Sopenharmony_ci		if (guid_equal(uuid_mod, uuid_tplg)) {
131862306a36Sopenharmony_ci			mconfig->module = skl_module;
131962306a36Sopenharmony_ci			ret = 0;
132062306a36Sopenharmony_ci			break;
132162306a36Sopenharmony_ci		}
132262306a36Sopenharmony_ci	}
132362306a36Sopenharmony_ci
132462306a36Sopenharmony_ci	if (skl->nr_modules && ret)
132562306a36Sopenharmony_ci		return ret;
132662306a36Sopenharmony_ci
132762306a36Sopenharmony_ci	ret = -EIO;
132862306a36Sopenharmony_ci	list_for_each_entry(module, &skl->uuid_list, list) {
132962306a36Sopenharmony_ci		if (guid_equal(uuid_mod, &module->uuid)) {
133062306a36Sopenharmony_ci			mconfig->id.module_id = module->id;
133162306a36Sopenharmony_ci			mconfig->module->loadable = module->is_loadable;
133262306a36Sopenharmony_ci			ret = 0;
133362306a36Sopenharmony_ci		}
133462306a36Sopenharmony_ci
133562306a36Sopenharmony_ci		for (i = 0; i < MAX_IN_QUEUE; i++) {
133662306a36Sopenharmony_ci			pin_id = &mconfig->m_in_pin[i].id;
133762306a36Sopenharmony_ci			if (guid_equal(&pin_id->mod_uuid, &module->uuid))
133862306a36Sopenharmony_ci				pin_id->module_id = module->id;
133962306a36Sopenharmony_ci		}
134062306a36Sopenharmony_ci
134162306a36Sopenharmony_ci		for (i = 0; i < MAX_OUT_QUEUE; i++) {
134262306a36Sopenharmony_ci			pin_id = &mconfig->m_out_pin[i].id;
134362306a36Sopenharmony_ci			if (guid_equal(&pin_id->mod_uuid, &module->uuid))
134462306a36Sopenharmony_ci				pin_id->module_id = module->id;
134562306a36Sopenharmony_ci		}
134662306a36Sopenharmony_ci	}
134762306a36Sopenharmony_ci
134862306a36Sopenharmony_ci	return ret;
134962306a36Sopenharmony_ci}
135062306a36Sopenharmony_ci
135162306a36Sopenharmony_cistatic int skl_populate_modules(struct skl_dev *skl)
135262306a36Sopenharmony_ci{
135362306a36Sopenharmony_ci	struct skl_pipeline *p;
135462306a36Sopenharmony_ci	struct skl_pipe_module *m;
135562306a36Sopenharmony_ci	struct snd_soc_dapm_widget *w;
135662306a36Sopenharmony_ci	struct skl_module_cfg *mconfig;
135762306a36Sopenharmony_ci	int ret = 0;
135862306a36Sopenharmony_ci
135962306a36Sopenharmony_ci	list_for_each_entry(p, &skl->ppl_list, node) {
136062306a36Sopenharmony_ci		list_for_each_entry(m, &p->pipe->w_list, node) {
136162306a36Sopenharmony_ci			w = m->w;
136262306a36Sopenharmony_ci			mconfig = w->priv;
136362306a36Sopenharmony_ci
136462306a36Sopenharmony_ci			ret = skl_get_module_info(skl, mconfig);
136562306a36Sopenharmony_ci			if (ret < 0) {
136662306a36Sopenharmony_ci				dev_err(skl->dev,
136762306a36Sopenharmony_ci					"query module info failed\n");
136862306a36Sopenharmony_ci				return ret;
136962306a36Sopenharmony_ci			}
137062306a36Sopenharmony_ci
137162306a36Sopenharmony_ci			skl_tplg_add_moduleid_in_bind_params(skl, w);
137262306a36Sopenharmony_ci		}
137362306a36Sopenharmony_ci	}
137462306a36Sopenharmony_ci
137562306a36Sopenharmony_ci	return ret;
137662306a36Sopenharmony_ci}
137762306a36Sopenharmony_ci
137862306a36Sopenharmony_cistatic int skl_platform_soc_probe(struct snd_soc_component *component)
137962306a36Sopenharmony_ci{
138062306a36Sopenharmony_ci	struct hdac_bus *bus = dev_get_drvdata(component->dev);
138162306a36Sopenharmony_ci	struct skl_dev *skl = bus_to_skl(bus);
138262306a36Sopenharmony_ci	const struct skl_dsp_ops *ops;
138362306a36Sopenharmony_ci	int ret;
138462306a36Sopenharmony_ci
138562306a36Sopenharmony_ci	ret = pm_runtime_resume_and_get(component->dev);
138662306a36Sopenharmony_ci	if (ret < 0 && ret != -EACCES)
138762306a36Sopenharmony_ci		return ret;
138862306a36Sopenharmony_ci
138962306a36Sopenharmony_ci	if (bus->ppcap) {
139062306a36Sopenharmony_ci		skl->component = component;
139162306a36Sopenharmony_ci
139262306a36Sopenharmony_ci		/* init debugfs */
139362306a36Sopenharmony_ci		skl->debugfs = skl_debugfs_init(skl);
139462306a36Sopenharmony_ci
139562306a36Sopenharmony_ci		ret = skl_tplg_init(component, bus);
139662306a36Sopenharmony_ci		if (ret < 0) {
139762306a36Sopenharmony_ci			dev_err(component->dev, "Failed to init topology!\n");
139862306a36Sopenharmony_ci			return ret;
139962306a36Sopenharmony_ci		}
140062306a36Sopenharmony_ci
140162306a36Sopenharmony_ci		/* load the firmwares, since all is set */
140262306a36Sopenharmony_ci		ops = skl_get_dsp_ops(skl->pci->device);
140362306a36Sopenharmony_ci		if (!ops)
140462306a36Sopenharmony_ci			return -EIO;
140562306a36Sopenharmony_ci
140662306a36Sopenharmony_ci		/*
140762306a36Sopenharmony_ci		 * Disable dynamic clock and power gating during firmware
140862306a36Sopenharmony_ci		 * and library download
140962306a36Sopenharmony_ci		 */
141062306a36Sopenharmony_ci		skl->enable_miscbdcge(component->dev, false);
141162306a36Sopenharmony_ci		skl->clock_power_gating(component->dev, false);
141262306a36Sopenharmony_ci
141362306a36Sopenharmony_ci		ret = ops->init_fw(component->dev, skl);
141462306a36Sopenharmony_ci		skl->enable_miscbdcge(component->dev, true);
141562306a36Sopenharmony_ci		skl->clock_power_gating(component->dev, true);
141662306a36Sopenharmony_ci		if (ret < 0) {
141762306a36Sopenharmony_ci			dev_err(component->dev, "Failed to boot first fw: %d\n", ret);
141862306a36Sopenharmony_ci			return ret;
141962306a36Sopenharmony_ci		}
142062306a36Sopenharmony_ci		skl_populate_modules(skl);
142162306a36Sopenharmony_ci		skl->update_d0i3c = skl_update_d0i3c;
142262306a36Sopenharmony_ci
142362306a36Sopenharmony_ci		if (skl->cfg.astate_cfg != NULL) {
142462306a36Sopenharmony_ci			skl_dsp_set_astate_cfg(skl,
142562306a36Sopenharmony_ci					skl->cfg.astate_cfg->count,
142662306a36Sopenharmony_ci					skl->cfg.astate_cfg);
142762306a36Sopenharmony_ci		}
142862306a36Sopenharmony_ci	}
142962306a36Sopenharmony_ci	pm_runtime_mark_last_busy(component->dev);
143062306a36Sopenharmony_ci	pm_runtime_put_autosuspend(component->dev);
143162306a36Sopenharmony_ci
143262306a36Sopenharmony_ci	return 0;
143362306a36Sopenharmony_ci}
143462306a36Sopenharmony_ci
143562306a36Sopenharmony_cistatic void skl_platform_soc_remove(struct snd_soc_component *component)
143662306a36Sopenharmony_ci{
143762306a36Sopenharmony_ci	struct hdac_bus *bus = dev_get_drvdata(component->dev);
143862306a36Sopenharmony_ci	struct skl_dev *skl = bus_to_skl(bus);
143962306a36Sopenharmony_ci
144062306a36Sopenharmony_ci	skl_tplg_exit(component, bus);
144162306a36Sopenharmony_ci
144262306a36Sopenharmony_ci	skl_debugfs_exit(skl);
144362306a36Sopenharmony_ci}
144462306a36Sopenharmony_ci
144562306a36Sopenharmony_cistatic const struct snd_soc_component_driver skl_component  = {
144662306a36Sopenharmony_ci	.name		= "pcm",
144762306a36Sopenharmony_ci	.probe		= skl_platform_soc_probe,
144862306a36Sopenharmony_ci	.remove		= skl_platform_soc_remove,
144962306a36Sopenharmony_ci	.open		= skl_platform_soc_open,
145062306a36Sopenharmony_ci	.trigger	= skl_platform_soc_trigger,
145162306a36Sopenharmony_ci	.pointer	= skl_platform_soc_pointer,
145262306a36Sopenharmony_ci	.get_time_info	= skl_platform_soc_get_time_info,
145362306a36Sopenharmony_ci	.pcm_construct	= skl_platform_soc_new,
145462306a36Sopenharmony_ci	.module_get_upon_open = 1, /* increment refcount when a pcm is opened */
145562306a36Sopenharmony_ci};
145662306a36Sopenharmony_ci
145762306a36Sopenharmony_ciint skl_platform_register(struct device *dev)
145862306a36Sopenharmony_ci{
145962306a36Sopenharmony_ci	int ret;
146062306a36Sopenharmony_ci	struct snd_soc_dai_driver *dais;
146162306a36Sopenharmony_ci	int num_dais = ARRAY_SIZE(skl_platform_dai);
146262306a36Sopenharmony_ci	struct hdac_bus *bus = dev_get_drvdata(dev);
146362306a36Sopenharmony_ci	struct skl_dev *skl = bus_to_skl(bus);
146462306a36Sopenharmony_ci
146562306a36Sopenharmony_ci	skl->dais = kmemdup(skl_platform_dai, sizeof(skl_platform_dai),
146662306a36Sopenharmony_ci			    GFP_KERNEL);
146762306a36Sopenharmony_ci	if (!skl->dais) {
146862306a36Sopenharmony_ci		ret = -ENOMEM;
146962306a36Sopenharmony_ci		goto err;
147062306a36Sopenharmony_ci	}
147162306a36Sopenharmony_ci
147262306a36Sopenharmony_ci	if (!skl->use_tplg_pcm) {
147362306a36Sopenharmony_ci		dais = krealloc(skl->dais, sizeof(skl_fe_dai) +
147462306a36Sopenharmony_ci				sizeof(skl_platform_dai), GFP_KERNEL);
147562306a36Sopenharmony_ci		if (!dais) {
147662306a36Sopenharmony_ci			kfree(skl->dais);
147762306a36Sopenharmony_ci			ret = -ENOMEM;
147862306a36Sopenharmony_ci			goto err;
147962306a36Sopenharmony_ci		}
148062306a36Sopenharmony_ci
148162306a36Sopenharmony_ci		skl->dais = dais;
148262306a36Sopenharmony_ci		memcpy(&skl->dais[ARRAY_SIZE(skl_platform_dai)], skl_fe_dai,
148362306a36Sopenharmony_ci		       sizeof(skl_fe_dai));
148462306a36Sopenharmony_ci		num_dais += ARRAY_SIZE(skl_fe_dai);
148562306a36Sopenharmony_ci	}
148662306a36Sopenharmony_ci
148762306a36Sopenharmony_ci	ret = devm_snd_soc_register_component(dev, &skl_component,
148862306a36Sopenharmony_ci					 skl->dais, num_dais);
148962306a36Sopenharmony_ci	if (ret) {
149062306a36Sopenharmony_ci		kfree(skl->dais);
149162306a36Sopenharmony_ci		dev_err(dev, "soc component registration failed %d\n", ret);
149262306a36Sopenharmony_ci	}
149362306a36Sopenharmony_cierr:
149462306a36Sopenharmony_ci	return ret;
149562306a36Sopenharmony_ci}
149662306a36Sopenharmony_ci
149762306a36Sopenharmony_ciint skl_platform_unregister(struct device *dev)
149862306a36Sopenharmony_ci{
149962306a36Sopenharmony_ci	struct hdac_bus *bus = dev_get_drvdata(dev);
150062306a36Sopenharmony_ci	struct skl_dev *skl = bus_to_skl(bus);
150162306a36Sopenharmony_ci	struct skl_module_deferred_bind *modules, *tmp;
150262306a36Sopenharmony_ci
150362306a36Sopenharmony_ci	list_for_each_entry_safe(modules, tmp, &skl->bind_list, node) {
150462306a36Sopenharmony_ci		list_del(&modules->node);
150562306a36Sopenharmony_ci		kfree(modules);
150662306a36Sopenharmony_ci	}
150762306a36Sopenharmony_ci
150862306a36Sopenharmony_ci	kfree(skl->dais);
150962306a36Sopenharmony_ci
151062306a36Sopenharmony_ci	return 0;
151162306a36Sopenharmony_ci}
1512