18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *  skl-message.c - HDA DSP interface for FW registration, Pipe and Module
48c2ecf20Sopenharmony_ci *  configurations
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci *  Copyright (C) 2015 Intel Corp
78c2ecf20Sopenharmony_ci *  Author:Rafal Redzimski <rafal.f.redzimski@intel.com>
88c2ecf20Sopenharmony_ci *	   Jeeja KP <jeeja.kp@intel.com>
98c2ecf20Sopenharmony_ci *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
108c2ecf20Sopenharmony_ci */
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#include <linux/slab.h>
138c2ecf20Sopenharmony_ci#include <linux/pci.h>
148c2ecf20Sopenharmony_ci#include <sound/core.h>
158c2ecf20Sopenharmony_ci#include <sound/pcm.h>
168c2ecf20Sopenharmony_ci#include <uapi/sound/skl-tplg-interface.h>
178c2ecf20Sopenharmony_ci#include "skl-sst-dsp.h"
188c2ecf20Sopenharmony_ci#include "cnl-sst-dsp.h"
198c2ecf20Sopenharmony_ci#include "skl-sst-ipc.h"
208c2ecf20Sopenharmony_ci#include "skl.h"
218c2ecf20Sopenharmony_ci#include "../common/sst-dsp.h"
228c2ecf20Sopenharmony_ci#include "../common/sst-dsp-priv.h"
238c2ecf20Sopenharmony_ci#include "skl-topology.h"
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_cistatic int skl_alloc_dma_buf(struct device *dev,
268c2ecf20Sopenharmony_ci		struct snd_dma_buffer *dmab, size_t size)
278c2ecf20Sopenharmony_ci{
288c2ecf20Sopenharmony_ci	return snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size, dmab);
298c2ecf20Sopenharmony_ci}
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_cistatic int skl_free_dma_buf(struct device *dev, struct snd_dma_buffer *dmab)
328c2ecf20Sopenharmony_ci{
338c2ecf20Sopenharmony_ci	snd_dma_free_pages(dmab);
348c2ecf20Sopenharmony_ci	return 0;
358c2ecf20Sopenharmony_ci}
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci#define SKL_ASTATE_PARAM_ID	4
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_civoid skl_dsp_set_astate_cfg(struct skl_dev *skl, u32 cnt, void *data)
408c2ecf20Sopenharmony_ci{
418c2ecf20Sopenharmony_ci	struct skl_ipc_large_config_msg	msg = {0};
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci	msg.large_param_id = SKL_ASTATE_PARAM_ID;
448c2ecf20Sopenharmony_ci	msg.param_data_size = (cnt * sizeof(struct skl_astate_param) +
458c2ecf20Sopenharmony_ci				sizeof(cnt));
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci	skl_ipc_set_large_config(&skl->ipc, &msg, data);
488c2ecf20Sopenharmony_ci}
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_cistatic int skl_dsp_setup_spib(struct device *dev, unsigned int size,
518c2ecf20Sopenharmony_ci				int stream_tag, int enable)
528c2ecf20Sopenharmony_ci{
538c2ecf20Sopenharmony_ci	struct hdac_bus *bus = dev_get_drvdata(dev);
548c2ecf20Sopenharmony_ci	struct hdac_stream *stream = snd_hdac_get_stream(bus,
558c2ecf20Sopenharmony_ci			SNDRV_PCM_STREAM_PLAYBACK, stream_tag);
568c2ecf20Sopenharmony_ci	struct hdac_ext_stream *estream;
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci	if (!stream)
598c2ecf20Sopenharmony_ci		return -EINVAL;
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci	estream = stream_to_hdac_ext_stream(stream);
628c2ecf20Sopenharmony_ci	/* enable/disable SPIB for this hdac stream */
638c2ecf20Sopenharmony_ci	snd_hdac_ext_stream_spbcap_enable(bus, enable, stream->index);
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci	/* set the spib value */
668c2ecf20Sopenharmony_ci	snd_hdac_ext_stream_set_spib(bus, estream, size);
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci	return 0;
698c2ecf20Sopenharmony_ci}
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_cistatic int skl_dsp_prepare(struct device *dev, unsigned int format,
728c2ecf20Sopenharmony_ci			unsigned int size, struct snd_dma_buffer *dmab)
738c2ecf20Sopenharmony_ci{
748c2ecf20Sopenharmony_ci	struct hdac_bus *bus = dev_get_drvdata(dev);
758c2ecf20Sopenharmony_ci	struct hdac_ext_stream *estream;
768c2ecf20Sopenharmony_ci	struct hdac_stream *stream;
778c2ecf20Sopenharmony_ci	struct snd_pcm_substream substream;
788c2ecf20Sopenharmony_ci	int ret;
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci	if (!bus)
818c2ecf20Sopenharmony_ci		return -ENODEV;
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci	memset(&substream, 0, sizeof(substream));
848c2ecf20Sopenharmony_ci	substream.stream = SNDRV_PCM_STREAM_PLAYBACK;
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci	estream = snd_hdac_ext_stream_assign(bus, &substream,
878c2ecf20Sopenharmony_ci					HDAC_EXT_STREAM_TYPE_HOST);
888c2ecf20Sopenharmony_ci	if (!estream)
898c2ecf20Sopenharmony_ci		return -ENODEV;
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	stream = hdac_stream(estream);
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	/* assign decouple host dma channel */
948c2ecf20Sopenharmony_ci	ret = snd_hdac_dsp_prepare(stream, format, size, dmab);
958c2ecf20Sopenharmony_ci	if (ret < 0)
968c2ecf20Sopenharmony_ci		return ret;
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci	skl_dsp_setup_spib(dev, size, stream->stream_tag, true);
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci	return stream->stream_tag;
1018c2ecf20Sopenharmony_ci}
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_cistatic int skl_dsp_trigger(struct device *dev, bool start, int stream_tag)
1048c2ecf20Sopenharmony_ci{
1058c2ecf20Sopenharmony_ci	struct hdac_bus *bus = dev_get_drvdata(dev);
1068c2ecf20Sopenharmony_ci	struct hdac_stream *stream;
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci	if (!bus)
1098c2ecf20Sopenharmony_ci		return -ENODEV;
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci	stream = snd_hdac_get_stream(bus,
1128c2ecf20Sopenharmony_ci		SNDRV_PCM_STREAM_PLAYBACK, stream_tag);
1138c2ecf20Sopenharmony_ci	if (!stream)
1148c2ecf20Sopenharmony_ci		return -EINVAL;
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci	snd_hdac_dsp_trigger(stream, start);
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci	return 0;
1198c2ecf20Sopenharmony_ci}
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_cistatic int skl_dsp_cleanup(struct device *dev,
1228c2ecf20Sopenharmony_ci		struct snd_dma_buffer *dmab, int stream_tag)
1238c2ecf20Sopenharmony_ci{
1248c2ecf20Sopenharmony_ci	struct hdac_bus *bus = dev_get_drvdata(dev);
1258c2ecf20Sopenharmony_ci	struct hdac_stream *stream;
1268c2ecf20Sopenharmony_ci	struct hdac_ext_stream *estream;
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci	if (!bus)
1298c2ecf20Sopenharmony_ci		return -ENODEV;
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	stream = snd_hdac_get_stream(bus,
1328c2ecf20Sopenharmony_ci		SNDRV_PCM_STREAM_PLAYBACK, stream_tag);
1338c2ecf20Sopenharmony_ci	if (!stream)
1348c2ecf20Sopenharmony_ci		return -EINVAL;
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci	estream = stream_to_hdac_ext_stream(stream);
1378c2ecf20Sopenharmony_ci	skl_dsp_setup_spib(dev, 0, stream_tag, false);
1388c2ecf20Sopenharmony_ci	snd_hdac_ext_stream_release(estream, HDAC_EXT_STREAM_TYPE_HOST);
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci	snd_hdac_dsp_cleanup(stream, dmab);
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci	return 0;
1438c2ecf20Sopenharmony_ci}
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_cistatic struct skl_dsp_loader_ops skl_get_loader_ops(void)
1468c2ecf20Sopenharmony_ci{
1478c2ecf20Sopenharmony_ci	struct skl_dsp_loader_ops loader_ops;
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci	memset(&loader_ops, 0, sizeof(struct skl_dsp_loader_ops));
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci	loader_ops.alloc_dma_buf = skl_alloc_dma_buf;
1528c2ecf20Sopenharmony_ci	loader_ops.free_dma_buf = skl_free_dma_buf;
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci	return loader_ops;
1558c2ecf20Sopenharmony_ci};
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_cistatic struct skl_dsp_loader_ops bxt_get_loader_ops(void)
1588c2ecf20Sopenharmony_ci{
1598c2ecf20Sopenharmony_ci	struct skl_dsp_loader_ops loader_ops;
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci	memset(&loader_ops, 0, sizeof(loader_ops));
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci	loader_ops.alloc_dma_buf = skl_alloc_dma_buf;
1648c2ecf20Sopenharmony_ci	loader_ops.free_dma_buf = skl_free_dma_buf;
1658c2ecf20Sopenharmony_ci	loader_ops.prepare = skl_dsp_prepare;
1668c2ecf20Sopenharmony_ci	loader_ops.trigger = skl_dsp_trigger;
1678c2ecf20Sopenharmony_ci	loader_ops.cleanup = skl_dsp_cleanup;
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ci	return loader_ops;
1708c2ecf20Sopenharmony_ci};
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_cistatic const struct skl_dsp_ops dsp_ops[] = {
1738c2ecf20Sopenharmony_ci	{
1748c2ecf20Sopenharmony_ci		.id = 0x9d70,
1758c2ecf20Sopenharmony_ci		.num_cores = 2,
1768c2ecf20Sopenharmony_ci		.loader_ops = skl_get_loader_ops,
1778c2ecf20Sopenharmony_ci		.init = skl_sst_dsp_init,
1788c2ecf20Sopenharmony_ci		.init_fw = skl_sst_init_fw,
1798c2ecf20Sopenharmony_ci		.cleanup = skl_sst_dsp_cleanup
1808c2ecf20Sopenharmony_ci	},
1818c2ecf20Sopenharmony_ci	{
1828c2ecf20Sopenharmony_ci		.id = 0x9d71,
1838c2ecf20Sopenharmony_ci		.num_cores = 2,
1848c2ecf20Sopenharmony_ci		.loader_ops = skl_get_loader_ops,
1858c2ecf20Sopenharmony_ci		.init = skl_sst_dsp_init,
1868c2ecf20Sopenharmony_ci		.init_fw = skl_sst_init_fw,
1878c2ecf20Sopenharmony_ci		.cleanup = skl_sst_dsp_cleanup
1888c2ecf20Sopenharmony_ci	},
1898c2ecf20Sopenharmony_ci	{
1908c2ecf20Sopenharmony_ci		.id = 0x5a98,
1918c2ecf20Sopenharmony_ci		.num_cores = 2,
1928c2ecf20Sopenharmony_ci		.loader_ops = bxt_get_loader_ops,
1938c2ecf20Sopenharmony_ci		.init = bxt_sst_dsp_init,
1948c2ecf20Sopenharmony_ci		.init_fw = bxt_sst_init_fw,
1958c2ecf20Sopenharmony_ci		.cleanup = bxt_sst_dsp_cleanup
1968c2ecf20Sopenharmony_ci	},
1978c2ecf20Sopenharmony_ci	{
1988c2ecf20Sopenharmony_ci		.id = 0x3198,
1998c2ecf20Sopenharmony_ci		.num_cores = 2,
2008c2ecf20Sopenharmony_ci		.loader_ops = bxt_get_loader_ops,
2018c2ecf20Sopenharmony_ci		.init = bxt_sst_dsp_init,
2028c2ecf20Sopenharmony_ci		.init_fw = bxt_sst_init_fw,
2038c2ecf20Sopenharmony_ci		.cleanup = bxt_sst_dsp_cleanup
2048c2ecf20Sopenharmony_ci	},
2058c2ecf20Sopenharmony_ci	{
2068c2ecf20Sopenharmony_ci		.id = 0x9dc8,
2078c2ecf20Sopenharmony_ci		.num_cores = 4,
2088c2ecf20Sopenharmony_ci		.loader_ops = bxt_get_loader_ops,
2098c2ecf20Sopenharmony_ci		.init = cnl_sst_dsp_init,
2108c2ecf20Sopenharmony_ci		.init_fw = cnl_sst_init_fw,
2118c2ecf20Sopenharmony_ci		.cleanup = cnl_sst_dsp_cleanup
2128c2ecf20Sopenharmony_ci	},
2138c2ecf20Sopenharmony_ci	{
2148c2ecf20Sopenharmony_ci		.id = 0xa348,
2158c2ecf20Sopenharmony_ci		.num_cores = 4,
2168c2ecf20Sopenharmony_ci		.loader_ops = bxt_get_loader_ops,
2178c2ecf20Sopenharmony_ci		.init = cnl_sst_dsp_init,
2188c2ecf20Sopenharmony_ci		.init_fw = cnl_sst_init_fw,
2198c2ecf20Sopenharmony_ci		.cleanup = cnl_sst_dsp_cleanup
2208c2ecf20Sopenharmony_ci	},
2218c2ecf20Sopenharmony_ci	{
2228c2ecf20Sopenharmony_ci		.id = 0x02c8,
2238c2ecf20Sopenharmony_ci		.num_cores = 4,
2248c2ecf20Sopenharmony_ci		.loader_ops = bxt_get_loader_ops,
2258c2ecf20Sopenharmony_ci		.init = cnl_sst_dsp_init,
2268c2ecf20Sopenharmony_ci		.init_fw = cnl_sst_init_fw,
2278c2ecf20Sopenharmony_ci		.cleanup = cnl_sst_dsp_cleanup
2288c2ecf20Sopenharmony_ci	},
2298c2ecf20Sopenharmony_ci	{
2308c2ecf20Sopenharmony_ci		.id = 0x06c8,
2318c2ecf20Sopenharmony_ci		.num_cores = 4,
2328c2ecf20Sopenharmony_ci		.loader_ops = bxt_get_loader_ops,
2338c2ecf20Sopenharmony_ci		.init = cnl_sst_dsp_init,
2348c2ecf20Sopenharmony_ci		.init_fw = cnl_sst_init_fw,
2358c2ecf20Sopenharmony_ci		.cleanup = cnl_sst_dsp_cleanup
2368c2ecf20Sopenharmony_ci	},
2378c2ecf20Sopenharmony_ci};
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ciconst struct skl_dsp_ops *skl_get_dsp_ops(int pci_id)
2408c2ecf20Sopenharmony_ci{
2418c2ecf20Sopenharmony_ci	int i;
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(dsp_ops); i++) {
2448c2ecf20Sopenharmony_ci		if (dsp_ops[i].id == pci_id)
2458c2ecf20Sopenharmony_ci			return &dsp_ops[i];
2468c2ecf20Sopenharmony_ci	}
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ci	return NULL;
2498c2ecf20Sopenharmony_ci}
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_ciint skl_init_dsp(struct skl_dev *skl)
2528c2ecf20Sopenharmony_ci{
2538c2ecf20Sopenharmony_ci	void __iomem *mmio_base;
2548c2ecf20Sopenharmony_ci	struct hdac_bus *bus = skl_to_bus(skl);
2558c2ecf20Sopenharmony_ci	struct skl_dsp_loader_ops loader_ops;
2568c2ecf20Sopenharmony_ci	int irq = bus->irq;
2578c2ecf20Sopenharmony_ci	const struct skl_dsp_ops *ops;
2588c2ecf20Sopenharmony_ci	struct skl_dsp_cores *cores;
2598c2ecf20Sopenharmony_ci	int ret;
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci	/* enable ppcap interrupt */
2628c2ecf20Sopenharmony_ci	snd_hdac_ext_bus_ppcap_enable(bus, true);
2638c2ecf20Sopenharmony_ci	snd_hdac_ext_bus_ppcap_int_enable(bus, true);
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ci	/* read the BAR of the ADSP MMIO */
2668c2ecf20Sopenharmony_ci	mmio_base = pci_ioremap_bar(skl->pci, 4);
2678c2ecf20Sopenharmony_ci	if (mmio_base == NULL) {
2688c2ecf20Sopenharmony_ci		dev_err(bus->dev, "ioremap error\n");
2698c2ecf20Sopenharmony_ci		return -ENXIO;
2708c2ecf20Sopenharmony_ci	}
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci	ops = skl_get_dsp_ops(skl->pci->device);
2738c2ecf20Sopenharmony_ci	if (!ops) {
2748c2ecf20Sopenharmony_ci		ret = -EIO;
2758c2ecf20Sopenharmony_ci		goto unmap_mmio;
2768c2ecf20Sopenharmony_ci	}
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci	loader_ops = ops->loader_ops();
2798c2ecf20Sopenharmony_ci	ret = ops->init(bus->dev, mmio_base, irq,
2808c2ecf20Sopenharmony_ci				skl->fw_name, loader_ops,
2818c2ecf20Sopenharmony_ci				&skl);
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ci	if (ret < 0)
2848c2ecf20Sopenharmony_ci		goto unmap_mmio;
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_ci	skl->dsp_ops = ops;
2878c2ecf20Sopenharmony_ci	cores = &skl->cores;
2888c2ecf20Sopenharmony_ci	cores->count = ops->num_cores;
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_ci	cores->state = kcalloc(cores->count, sizeof(*cores->state), GFP_KERNEL);
2918c2ecf20Sopenharmony_ci	if (!cores->state) {
2928c2ecf20Sopenharmony_ci		ret = -ENOMEM;
2938c2ecf20Sopenharmony_ci		goto unmap_mmio;
2948c2ecf20Sopenharmony_ci	}
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_ci	cores->usage_count = kcalloc(cores->count, sizeof(*cores->usage_count),
2978c2ecf20Sopenharmony_ci				     GFP_KERNEL);
2988c2ecf20Sopenharmony_ci	if (!cores->usage_count) {
2998c2ecf20Sopenharmony_ci		ret = -ENOMEM;
3008c2ecf20Sopenharmony_ci		goto free_core_state;
3018c2ecf20Sopenharmony_ci	}
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ci	dev_dbg(bus->dev, "dsp registration status=%d\n", ret);
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci	return 0;
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_cifree_core_state:
3088c2ecf20Sopenharmony_ci	kfree(cores->state);
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_ciunmap_mmio:
3118c2ecf20Sopenharmony_ci	iounmap(mmio_base);
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_ci	return ret;
3148c2ecf20Sopenharmony_ci}
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ciint skl_free_dsp(struct skl_dev *skl)
3178c2ecf20Sopenharmony_ci{
3188c2ecf20Sopenharmony_ci	struct hdac_bus *bus = skl_to_bus(skl);
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ci	/* disable  ppcap interrupt */
3218c2ecf20Sopenharmony_ci	snd_hdac_ext_bus_ppcap_int_enable(bus, false);
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_ci	skl->dsp_ops->cleanup(bus->dev, skl);
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci	kfree(skl->cores.state);
3268c2ecf20Sopenharmony_ci	kfree(skl->cores.usage_count);
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_ci	if (skl->dsp->addr.lpe)
3298c2ecf20Sopenharmony_ci		iounmap(skl->dsp->addr.lpe);
3308c2ecf20Sopenharmony_ci
3318c2ecf20Sopenharmony_ci	return 0;
3328c2ecf20Sopenharmony_ci}
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_ci/*
3358c2ecf20Sopenharmony_ci * In the case of "suspend_active" i.e, the Audio IP being active
3368c2ecf20Sopenharmony_ci * during system suspend, immediately excecute any pending D0i3 work
3378c2ecf20Sopenharmony_ci * before suspending. This is needed for the IP to work in low power
3388c2ecf20Sopenharmony_ci * mode during system suspend. In the case of normal suspend, cancel
3398c2ecf20Sopenharmony_ci * any pending D0i3 work.
3408c2ecf20Sopenharmony_ci */
3418c2ecf20Sopenharmony_ciint skl_suspend_late_dsp(struct skl_dev *skl)
3428c2ecf20Sopenharmony_ci{
3438c2ecf20Sopenharmony_ci	struct delayed_work *dwork;
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_ci	if (!skl)
3468c2ecf20Sopenharmony_ci		return 0;
3478c2ecf20Sopenharmony_ci
3488c2ecf20Sopenharmony_ci	dwork = &skl->d0i3.work;
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_ci	if (dwork->work.func) {
3518c2ecf20Sopenharmony_ci		if (skl->supend_active)
3528c2ecf20Sopenharmony_ci			flush_delayed_work(dwork);
3538c2ecf20Sopenharmony_ci		else
3548c2ecf20Sopenharmony_ci			cancel_delayed_work_sync(dwork);
3558c2ecf20Sopenharmony_ci	}
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_ci	return 0;
3588c2ecf20Sopenharmony_ci}
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_ciint skl_suspend_dsp(struct skl_dev *skl)
3618c2ecf20Sopenharmony_ci{
3628c2ecf20Sopenharmony_ci	struct hdac_bus *bus = skl_to_bus(skl);
3638c2ecf20Sopenharmony_ci	int ret;
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ci	/* if ppcap is not supported return 0 */
3668c2ecf20Sopenharmony_ci	if (!bus->ppcap)
3678c2ecf20Sopenharmony_ci		return 0;
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_ci	ret = skl_dsp_sleep(skl->dsp);
3708c2ecf20Sopenharmony_ci	if (ret < 0)
3718c2ecf20Sopenharmony_ci		return ret;
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_ci	/* disable ppcap interrupt */
3748c2ecf20Sopenharmony_ci	snd_hdac_ext_bus_ppcap_int_enable(bus, false);
3758c2ecf20Sopenharmony_ci	snd_hdac_ext_bus_ppcap_enable(bus, false);
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_ci	return 0;
3788c2ecf20Sopenharmony_ci}
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_ciint skl_resume_dsp(struct skl_dev *skl)
3818c2ecf20Sopenharmony_ci{
3828c2ecf20Sopenharmony_ci	struct hdac_bus *bus = skl_to_bus(skl);
3838c2ecf20Sopenharmony_ci	int ret;
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_ci	/* if ppcap is not supported return 0 */
3868c2ecf20Sopenharmony_ci	if (!bus->ppcap)
3878c2ecf20Sopenharmony_ci		return 0;
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_ci	/* enable ppcap interrupt */
3908c2ecf20Sopenharmony_ci	snd_hdac_ext_bus_ppcap_enable(bus, true);
3918c2ecf20Sopenharmony_ci	snd_hdac_ext_bus_ppcap_int_enable(bus, true);
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_ci	/* check if DSP 1st boot is done */
3948c2ecf20Sopenharmony_ci	if (skl->is_first_boot)
3958c2ecf20Sopenharmony_ci		return 0;
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_ci	/*
3988c2ecf20Sopenharmony_ci	 * Disable dynamic clock and power gating during firmware
3998c2ecf20Sopenharmony_ci	 * and library download
4008c2ecf20Sopenharmony_ci	 */
4018c2ecf20Sopenharmony_ci	skl->enable_miscbdcge(skl->dev, false);
4028c2ecf20Sopenharmony_ci	skl->clock_power_gating(skl->dev, false);
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_ci	ret = skl_dsp_wake(skl->dsp);
4058c2ecf20Sopenharmony_ci	skl->enable_miscbdcge(skl->dev, true);
4068c2ecf20Sopenharmony_ci	skl->clock_power_gating(skl->dev, true);
4078c2ecf20Sopenharmony_ci	if (ret < 0)
4088c2ecf20Sopenharmony_ci		return ret;
4098c2ecf20Sopenharmony_ci
4108c2ecf20Sopenharmony_ci	if (skl->cfg.astate_cfg != NULL) {
4118c2ecf20Sopenharmony_ci		skl_dsp_set_astate_cfg(skl, skl->cfg.astate_cfg->count,
4128c2ecf20Sopenharmony_ci					skl->cfg.astate_cfg);
4138c2ecf20Sopenharmony_ci	}
4148c2ecf20Sopenharmony_ci	return ret;
4158c2ecf20Sopenharmony_ci}
4168c2ecf20Sopenharmony_ci
4178c2ecf20Sopenharmony_cienum skl_bitdepth skl_get_bit_depth(int params)
4188c2ecf20Sopenharmony_ci{
4198c2ecf20Sopenharmony_ci	switch (params) {
4208c2ecf20Sopenharmony_ci	case 8:
4218c2ecf20Sopenharmony_ci		return SKL_DEPTH_8BIT;
4228c2ecf20Sopenharmony_ci
4238c2ecf20Sopenharmony_ci	case 16:
4248c2ecf20Sopenharmony_ci		return SKL_DEPTH_16BIT;
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_ci	case 24:
4278c2ecf20Sopenharmony_ci		return SKL_DEPTH_24BIT;
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_ci	case 32:
4308c2ecf20Sopenharmony_ci		return SKL_DEPTH_32BIT;
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ci	default:
4338c2ecf20Sopenharmony_ci		return SKL_DEPTH_INVALID;
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_ci	}
4368c2ecf20Sopenharmony_ci}
4378c2ecf20Sopenharmony_ci
4388c2ecf20Sopenharmony_ci/*
4398c2ecf20Sopenharmony_ci * Each module in DSP expects a base module configuration, which consists of
4408c2ecf20Sopenharmony_ci * PCM format information, which we calculate in driver and resource values
4418c2ecf20Sopenharmony_ci * which are read from widget information passed through topology binary
4428c2ecf20Sopenharmony_ci * This is send when we create a module with INIT_INSTANCE IPC msg
4438c2ecf20Sopenharmony_ci */
4448c2ecf20Sopenharmony_cistatic void skl_set_base_module_format(struct skl_dev *skl,
4458c2ecf20Sopenharmony_ci			struct skl_module_cfg *mconfig,
4468c2ecf20Sopenharmony_ci			struct skl_base_cfg *base_cfg)
4478c2ecf20Sopenharmony_ci{
4488c2ecf20Sopenharmony_ci	struct skl_module *module = mconfig->module;
4498c2ecf20Sopenharmony_ci	struct skl_module_res *res = &module->resources[mconfig->res_idx];
4508c2ecf20Sopenharmony_ci	struct skl_module_iface *fmt = &module->formats[mconfig->fmt_idx];
4518c2ecf20Sopenharmony_ci	struct skl_module_fmt *format = &fmt->inputs[0].fmt;
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci	base_cfg->audio_fmt.number_of_channels = format->channels;
4548c2ecf20Sopenharmony_ci
4558c2ecf20Sopenharmony_ci	base_cfg->audio_fmt.s_freq = format->s_freq;
4568c2ecf20Sopenharmony_ci	base_cfg->audio_fmt.bit_depth = format->bit_depth;
4578c2ecf20Sopenharmony_ci	base_cfg->audio_fmt.valid_bit_depth = format->valid_bit_depth;
4588c2ecf20Sopenharmony_ci	base_cfg->audio_fmt.ch_cfg = format->ch_cfg;
4598c2ecf20Sopenharmony_ci	base_cfg->audio_fmt.sample_type = format->sample_type;
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_ci	dev_dbg(skl->dev, "bit_depth=%x valid_bd=%x ch_config=%x\n",
4628c2ecf20Sopenharmony_ci			format->bit_depth, format->valid_bit_depth,
4638c2ecf20Sopenharmony_ci			format->ch_cfg);
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_ci	base_cfg->audio_fmt.channel_map = format->ch_map;
4668c2ecf20Sopenharmony_ci
4678c2ecf20Sopenharmony_ci	base_cfg->audio_fmt.interleaving = format->interleaving_style;
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_ci	base_cfg->cpc = res->cpc;
4708c2ecf20Sopenharmony_ci	base_cfg->ibs = res->ibs;
4718c2ecf20Sopenharmony_ci	base_cfg->obs = res->obs;
4728c2ecf20Sopenharmony_ci	base_cfg->is_pages = res->is_pages;
4738c2ecf20Sopenharmony_ci}
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci/*
4768c2ecf20Sopenharmony_ci * Copies copier capabilities into copier module and updates copier module
4778c2ecf20Sopenharmony_ci * config size.
4788c2ecf20Sopenharmony_ci */
4798c2ecf20Sopenharmony_cistatic void skl_copy_copier_caps(struct skl_module_cfg *mconfig,
4808c2ecf20Sopenharmony_ci				struct skl_cpr_cfg *cpr_mconfig)
4818c2ecf20Sopenharmony_ci{
4828c2ecf20Sopenharmony_ci	if (mconfig->formats_config.caps_size == 0)
4838c2ecf20Sopenharmony_ci		return;
4848c2ecf20Sopenharmony_ci
4858c2ecf20Sopenharmony_ci	memcpy(cpr_mconfig->gtw_cfg.config_data,
4868c2ecf20Sopenharmony_ci			mconfig->formats_config.caps,
4878c2ecf20Sopenharmony_ci			mconfig->formats_config.caps_size);
4888c2ecf20Sopenharmony_ci
4898c2ecf20Sopenharmony_ci	cpr_mconfig->gtw_cfg.config_length =
4908c2ecf20Sopenharmony_ci			(mconfig->formats_config.caps_size) / 4;
4918c2ecf20Sopenharmony_ci}
4928c2ecf20Sopenharmony_ci
4938c2ecf20Sopenharmony_ci#define SKL_NON_GATEWAY_CPR_NODE_ID 0xFFFFFFFF
4948c2ecf20Sopenharmony_ci/*
4958c2ecf20Sopenharmony_ci * Calculate the gatewat settings required for copier module, type of
4968c2ecf20Sopenharmony_ci * gateway and index of gateway to use
4978c2ecf20Sopenharmony_ci */
4988c2ecf20Sopenharmony_cistatic u32 skl_get_node_id(struct skl_dev *skl,
4998c2ecf20Sopenharmony_ci			struct skl_module_cfg *mconfig)
5008c2ecf20Sopenharmony_ci{
5018c2ecf20Sopenharmony_ci	union skl_connector_node_id node_id = {0};
5028c2ecf20Sopenharmony_ci	union skl_ssp_dma_node ssp_node  = {0};
5038c2ecf20Sopenharmony_ci	struct skl_pipe_params *params = mconfig->pipe->p_params;
5048c2ecf20Sopenharmony_ci
5058c2ecf20Sopenharmony_ci	switch (mconfig->dev_type) {
5068c2ecf20Sopenharmony_ci	case SKL_DEVICE_BT:
5078c2ecf20Sopenharmony_ci		node_id.node.dma_type =
5088c2ecf20Sopenharmony_ci			(SKL_CONN_SOURCE == mconfig->hw_conn_type) ?
5098c2ecf20Sopenharmony_ci			SKL_DMA_I2S_LINK_OUTPUT_CLASS :
5108c2ecf20Sopenharmony_ci			SKL_DMA_I2S_LINK_INPUT_CLASS;
5118c2ecf20Sopenharmony_ci		node_id.node.vindex = params->host_dma_id +
5128c2ecf20Sopenharmony_ci					(mconfig->vbus_id << 3);
5138c2ecf20Sopenharmony_ci		break;
5148c2ecf20Sopenharmony_ci
5158c2ecf20Sopenharmony_ci	case SKL_DEVICE_I2S:
5168c2ecf20Sopenharmony_ci		node_id.node.dma_type =
5178c2ecf20Sopenharmony_ci			(SKL_CONN_SOURCE == mconfig->hw_conn_type) ?
5188c2ecf20Sopenharmony_ci			SKL_DMA_I2S_LINK_OUTPUT_CLASS :
5198c2ecf20Sopenharmony_ci			SKL_DMA_I2S_LINK_INPUT_CLASS;
5208c2ecf20Sopenharmony_ci		ssp_node.dma_node.time_slot_index = mconfig->time_slot;
5218c2ecf20Sopenharmony_ci		ssp_node.dma_node.i2s_instance = mconfig->vbus_id;
5228c2ecf20Sopenharmony_ci		node_id.node.vindex = ssp_node.val;
5238c2ecf20Sopenharmony_ci		break;
5248c2ecf20Sopenharmony_ci
5258c2ecf20Sopenharmony_ci	case SKL_DEVICE_DMIC:
5268c2ecf20Sopenharmony_ci		node_id.node.dma_type = SKL_DMA_DMIC_LINK_INPUT_CLASS;
5278c2ecf20Sopenharmony_ci		node_id.node.vindex = mconfig->vbus_id +
5288c2ecf20Sopenharmony_ci					 (mconfig->time_slot);
5298c2ecf20Sopenharmony_ci		break;
5308c2ecf20Sopenharmony_ci
5318c2ecf20Sopenharmony_ci	case SKL_DEVICE_HDALINK:
5328c2ecf20Sopenharmony_ci		node_id.node.dma_type =
5338c2ecf20Sopenharmony_ci			(SKL_CONN_SOURCE == mconfig->hw_conn_type) ?
5348c2ecf20Sopenharmony_ci			SKL_DMA_HDA_LINK_OUTPUT_CLASS :
5358c2ecf20Sopenharmony_ci			SKL_DMA_HDA_LINK_INPUT_CLASS;
5368c2ecf20Sopenharmony_ci		node_id.node.vindex = params->link_dma_id;
5378c2ecf20Sopenharmony_ci		break;
5388c2ecf20Sopenharmony_ci
5398c2ecf20Sopenharmony_ci	case SKL_DEVICE_HDAHOST:
5408c2ecf20Sopenharmony_ci		node_id.node.dma_type =
5418c2ecf20Sopenharmony_ci			(SKL_CONN_SOURCE == mconfig->hw_conn_type) ?
5428c2ecf20Sopenharmony_ci			SKL_DMA_HDA_HOST_OUTPUT_CLASS :
5438c2ecf20Sopenharmony_ci			SKL_DMA_HDA_HOST_INPUT_CLASS;
5448c2ecf20Sopenharmony_ci		node_id.node.vindex = params->host_dma_id;
5458c2ecf20Sopenharmony_ci		break;
5468c2ecf20Sopenharmony_ci
5478c2ecf20Sopenharmony_ci	default:
5488c2ecf20Sopenharmony_ci		node_id.val = 0xFFFFFFFF;
5498c2ecf20Sopenharmony_ci		break;
5508c2ecf20Sopenharmony_ci	}
5518c2ecf20Sopenharmony_ci
5528c2ecf20Sopenharmony_ci	return node_id.val;
5538c2ecf20Sopenharmony_ci}
5548c2ecf20Sopenharmony_ci
5558c2ecf20Sopenharmony_cistatic void skl_setup_cpr_gateway_cfg(struct skl_dev *skl,
5568c2ecf20Sopenharmony_ci			struct skl_module_cfg *mconfig,
5578c2ecf20Sopenharmony_ci			struct skl_cpr_cfg *cpr_mconfig)
5588c2ecf20Sopenharmony_ci{
5598c2ecf20Sopenharmony_ci	u32 dma_io_buf;
5608c2ecf20Sopenharmony_ci	struct skl_module_res *res;
5618c2ecf20Sopenharmony_ci	int res_idx = mconfig->res_idx;
5628c2ecf20Sopenharmony_ci
5638c2ecf20Sopenharmony_ci	cpr_mconfig->gtw_cfg.node_id = skl_get_node_id(skl, mconfig);
5648c2ecf20Sopenharmony_ci
5658c2ecf20Sopenharmony_ci	if (cpr_mconfig->gtw_cfg.node_id == SKL_NON_GATEWAY_CPR_NODE_ID) {
5668c2ecf20Sopenharmony_ci		cpr_mconfig->cpr_feature_mask = 0;
5678c2ecf20Sopenharmony_ci		return;
5688c2ecf20Sopenharmony_ci	}
5698c2ecf20Sopenharmony_ci
5708c2ecf20Sopenharmony_ci	if (skl->nr_modules) {
5718c2ecf20Sopenharmony_ci		res = &mconfig->module->resources[mconfig->res_idx];
5728c2ecf20Sopenharmony_ci		cpr_mconfig->gtw_cfg.dma_buffer_size = res->dma_buffer_size;
5738c2ecf20Sopenharmony_ci		goto skip_buf_size_calc;
5748c2ecf20Sopenharmony_ci	} else {
5758c2ecf20Sopenharmony_ci		res = &mconfig->module->resources[res_idx];
5768c2ecf20Sopenharmony_ci	}
5778c2ecf20Sopenharmony_ci
5788c2ecf20Sopenharmony_ci	switch (mconfig->hw_conn_type) {
5798c2ecf20Sopenharmony_ci	case SKL_CONN_SOURCE:
5808c2ecf20Sopenharmony_ci		if (mconfig->dev_type == SKL_DEVICE_HDAHOST)
5818c2ecf20Sopenharmony_ci			dma_io_buf =  res->ibs;
5828c2ecf20Sopenharmony_ci		else
5838c2ecf20Sopenharmony_ci			dma_io_buf =  res->obs;
5848c2ecf20Sopenharmony_ci		break;
5858c2ecf20Sopenharmony_ci
5868c2ecf20Sopenharmony_ci	case SKL_CONN_SINK:
5878c2ecf20Sopenharmony_ci		if (mconfig->dev_type == SKL_DEVICE_HDAHOST)
5888c2ecf20Sopenharmony_ci			dma_io_buf =  res->obs;
5898c2ecf20Sopenharmony_ci		else
5908c2ecf20Sopenharmony_ci			dma_io_buf =  res->ibs;
5918c2ecf20Sopenharmony_ci		break;
5928c2ecf20Sopenharmony_ci
5938c2ecf20Sopenharmony_ci	default:
5948c2ecf20Sopenharmony_ci		dev_warn(skl->dev, "wrong connection type: %d\n",
5958c2ecf20Sopenharmony_ci				mconfig->hw_conn_type);
5968c2ecf20Sopenharmony_ci		return;
5978c2ecf20Sopenharmony_ci	}
5988c2ecf20Sopenharmony_ci
5998c2ecf20Sopenharmony_ci	cpr_mconfig->gtw_cfg.dma_buffer_size =
6008c2ecf20Sopenharmony_ci				mconfig->dma_buffer_size * dma_io_buf;
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_ci	/* fallback to 2ms default value */
6038c2ecf20Sopenharmony_ci	if (!cpr_mconfig->gtw_cfg.dma_buffer_size) {
6048c2ecf20Sopenharmony_ci		if (mconfig->hw_conn_type == SKL_CONN_SOURCE)
6058c2ecf20Sopenharmony_ci			cpr_mconfig->gtw_cfg.dma_buffer_size = 2 * res->obs;
6068c2ecf20Sopenharmony_ci		else
6078c2ecf20Sopenharmony_ci			cpr_mconfig->gtw_cfg.dma_buffer_size = 2 * res->ibs;
6088c2ecf20Sopenharmony_ci	}
6098c2ecf20Sopenharmony_ci
6108c2ecf20Sopenharmony_ciskip_buf_size_calc:
6118c2ecf20Sopenharmony_ci	cpr_mconfig->cpr_feature_mask = 0;
6128c2ecf20Sopenharmony_ci	cpr_mconfig->gtw_cfg.config_length  = 0;
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_ci	skl_copy_copier_caps(mconfig, cpr_mconfig);
6158c2ecf20Sopenharmony_ci}
6168c2ecf20Sopenharmony_ci
6178c2ecf20Sopenharmony_ci#define DMA_CONTROL_ID 5
6188c2ecf20Sopenharmony_ci#define DMA_I2S_BLOB_SIZE 21
6198c2ecf20Sopenharmony_ci
6208c2ecf20Sopenharmony_ciint skl_dsp_set_dma_control(struct skl_dev *skl, u32 *caps,
6218c2ecf20Sopenharmony_ci				u32 caps_size, u32 node_id)
6228c2ecf20Sopenharmony_ci{
6238c2ecf20Sopenharmony_ci	struct skl_dma_control *dma_ctrl;
6248c2ecf20Sopenharmony_ci	struct skl_ipc_large_config_msg msg = {0};
6258c2ecf20Sopenharmony_ci	int err = 0;
6268c2ecf20Sopenharmony_ci
6278c2ecf20Sopenharmony_ci
6288c2ecf20Sopenharmony_ci	/*
6298c2ecf20Sopenharmony_ci	 * if blob size zero, then return
6308c2ecf20Sopenharmony_ci	 */
6318c2ecf20Sopenharmony_ci	if (caps_size == 0)
6328c2ecf20Sopenharmony_ci		return 0;
6338c2ecf20Sopenharmony_ci
6348c2ecf20Sopenharmony_ci	msg.large_param_id = DMA_CONTROL_ID;
6358c2ecf20Sopenharmony_ci	msg.param_data_size = sizeof(struct skl_dma_control) + caps_size;
6368c2ecf20Sopenharmony_ci
6378c2ecf20Sopenharmony_ci	dma_ctrl = kzalloc(msg.param_data_size, GFP_KERNEL);
6388c2ecf20Sopenharmony_ci	if (dma_ctrl == NULL)
6398c2ecf20Sopenharmony_ci		return -ENOMEM;
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_ci	dma_ctrl->node_id = node_id;
6428c2ecf20Sopenharmony_ci
6438c2ecf20Sopenharmony_ci	/*
6448c2ecf20Sopenharmony_ci	 * NHLT blob may contain additional configs along with i2s blob.
6458c2ecf20Sopenharmony_ci	 * firmware expects only the i2s blob size as the config_length.
6468c2ecf20Sopenharmony_ci	 * So fix to i2s blob size.
6478c2ecf20Sopenharmony_ci	 * size in dwords.
6488c2ecf20Sopenharmony_ci	 */
6498c2ecf20Sopenharmony_ci	dma_ctrl->config_length = DMA_I2S_BLOB_SIZE;
6508c2ecf20Sopenharmony_ci
6518c2ecf20Sopenharmony_ci	memcpy(dma_ctrl->config_data, caps, caps_size);
6528c2ecf20Sopenharmony_ci
6538c2ecf20Sopenharmony_ci	err = skl_ipc_set_large_config(&skl->ipc, &msg, (u32 *)dma_ctrl);
6548c2ecf20Sopenharmony_ci
6558c2ecf20Sopenharmony_ci	kfree(dma_ctrl);
6568c2ecf20Sopenharmony_ci	return err;
6578c2ecf20Sopenharmony_ci}
6588c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(skl_dsp_set_dma_control);
6598c2ecf20Sopenharmony_ci
6608c2ecf20Sopenharmony_cistatic void skl_setup_out_format(struct skl_dev *skl,
6618c2ecf20Sopenharmony_ci			struct skl_module_cfg *mconfig,
6628c2ecf20Sopenharmony_ci			struct skl_audio_data_format *out_fmt)
6638c2ecf20Sopenharmony_ci{
6648c2ecf20Sopenharmony_ci	struct skl_module *module = mconfig->module;
6658c2ecf20Sopenharmony_ci	struct skl_module_iface *fmt = &module->formats[mconfig->fmt_idx];
6668c2ecf20Sopenharmony_ci	struct skl_module_fmt *format = &fmt->outputs[0].fmt;
6678c2ecf20Sopenharmony_ci
6688c2ecf20Sopenharmony_ci	out_fmt->number_of_channels = (u8)format->channels;
6698c2ecf20Sopenharmony_ci	out_fmt->s_freq = format->s_freq;
6708c2ecf20Sopenharmony_ci	out_fmt->bit_depth = format->bit_depth;
6718c2ecf20Sopenharmony_ci	out_fmt->valid_bit_depth = format->valid_bit_depth;
6728c2ecf20Sopenharmony_ci	out_fmt->ch_cfg = format->ch_cfg;
6738c2ecf20Sopenharmony_ci
6748c2ecf20Sopenharmony_ci	out_fmt->channel_map = format->ch_map;
6758c2ecf20Sopenharmony_ci	out_fmt->interleaving = format->interleaving_style;
6768c2ecf20Sopenharmony_ci	out_fmt->sample_type = format->sample_type;
6778c2ecf20Sopenharmony_ci
6788c2ecf20Sopenharmony_ci	dev_dbg(skl->dev, "copier out format chan=%d fre=%d bitdepth=%d\n",
6798c2ecf20Sopenharmony_ci		out_fmt->number_of_channels, format->s_freq, format->bit_depth);
6808c2ecf20Sopenharmony_ci}
6818c2ecf20Sopenharmony_ci
6828c2ecf20Sopenharmony_ci/*
6838c2ecf20Sopenharmony_ci * DSP needs SRC module for frequency conversion, SRC takes base module
6848c2ecf20Sopenharmony_ci * configuration and the target frequency as extra parameter passed as src
6858c2ecf20Sopenharmony_ci * config
6868c2ecf20Sopenharmony_ci */
6878c2ecf20Sopenharmony_cistatic void skl_set_src_format(struct skl_dev *skl,
6888c2ecf20Sopenharmony_ci			struct skl_module_cfg *mconfig,
6898c2ecf20Sopenharmony_ci			struct skl_src_module_cfg *src_mconfig)
6908c2ecf20Sopenharmony_ci{
6918c2ecf20Sopenharmony_ci	struct skl_module *module = mconfig->module;
6928c2ecf20Sopenharmony_ci	struct skl_module_iface *iface = &module->formats[mconfig->fmt_idx];
6938c2ecf20Sopenharmony_ci	struct skl_module_fmt *fmt = &iface->outputs[0].fmt;
6948c2ecf20Sopenharmony_ci
6958c2ecf20Sopenharmony_ci	skl_set_base_module_format(skl, mconfig,
6968c2ecf20Sopenharmony_ci		(struct skl_base_cfg *)src_mconfig);
6978c2ecf20Sopenharmony_ci
6988c2ecf20Sopenharmony_ci	src_mconfig->src_cfg = fmt->s_freq;
6998c2ecf20Sopenharmony_ci}
7008c2ecf20Sopenharmony_ci
7018c2ecf20Sopenharmony_ci/*
7028c2ecf20Sopenharmony_ci * DSP needs updown module to do channel conversion. updown module take base
7038c2ecf20Sopenharmony_ci * module configuration and channel configuration
7048c2ecf20Sopenharmony_ci * It also take coefficients and now we have defaults applied here
7058c2ecf20Sopenharmony_ci */
7068c2ecf20Sopenharmony_cistatic void skl_set_updown_mixer_format(struct skl_dev *skl,
7078c2ecf20Sopenharmony_ci			struct skl_module_cfg *mconfig,
7088c2ecf20Sopenharmony_ci			struct skl_up_down_mixer_cfg *mixer_mconfig)
7098c2ecf20Sopenharmony_ci{
7108c2ecf20Sopenharmony_ci	struct skl_module *module = mconfig->module;
7118c2ecf20Sopenharmony_ci	struct skl_module_iface *iface = &module->formats[mconfig->fmt_idx];
7128c2ecf20Sopenharmony_ci	struct skl_module_fmt *fmt = &iface->outputs[0].fmt;
7138c2ecf20Sopenharmony_ci
7148c2ecf20Sopenharmony_ci	skl_set_base_module_format(skl,	mconfig,
7158c2ecf20Sopenharmony_ci		(struct skl_base_cfg *)mixer_mconfig);
7168c2ecf20Sopenharmony_ci	mixer_mconfig->out_ch_cfg = fmt->ch_cfg;
7178c2ecf20Sopenharmony_ci	mixer_mconfig->ch_map = fmt->ch_map;
7188c2ecf20Sopenharmony_ci}
7198c2ecf20Sopenharmony_ci
7208c2ecf20Sopenharmony_ci/*
7218c2ecf20Sopenharmony_ci * 'copier' is DSP internal module which copies data from Host DMA (HDA host
7228c2ecf20Sopenharmony_ci * dma) or link (hda link, SSP, PDM)
7238c2ecf20Sopenharmony_ci * Here we calculate the copier module parameters, like PCM format, output
7248c2ecf20Sopenharmony_ci * format, gateway settings
7258c2ecf20Sopenharmony_ci * copier_module_config is sent as input buffer with INIT_INSTANCE IPC msg
7268c2ecf20Sopenharmony_ci */
7278c2ecf20Sopenharmony_cistatic void skl_set_copier_format(struct skl_dev *skl,
7288c2ecf20Sopenharmony_ci			struct skl_module_cfg *mconfig,
7298c2ecf20Sopenharmony_ci			struct skl_cpr_cfg *cpr_mconfig)
7308c2ecf20Sopenharmony_ci{
7318c2ecf20Sopenharmony_ci	struct skl_audio_data_format *out_fmt = &cpr_mconfig->out_fmt;
7328c2ecf20Sopenharmony_ci	struct skl_base_cfg *base_cfg = (struct skl_base_cfg *)cpr_mconfig;
7338c2ecf20Sopenharmony_ci
7348c2ecf20Sopenharmony_ci	skl_set_base_module_format(skl, mconfig, base_cfg);
7358c2ecf20Sopenharmony_ci
7368c2ecf20Sopenharmony_ci	skl_setup_out_format(skl, mconfig, out_fmt);
7378c2ecf20Sopenharmony_ci	skl_setup_cpr_gateway_cfg(skl, mconfig, cpr_mconfig);
7388c2ecf20Sopenharmony_ci}
7398c2ecf20Sopenharmony_ci
7408c2ecf20Sopenharmony_ci/*
7418c2ecf20Sopenharmony_ci * Algo module are DSP pre processing modules. Algo module take base module
7428c2ecf20Sopenharmony_ci * configuration and params
7438c2ecf20Sopenharmony_ci */
7448c2ecf20Sopenharmony_ci
7458c2ecf20Sopenharmony_cistatic void skl_set_algo_format(struct skl_dev *skl,
7468c2ecf20Sopenharmony_ci			struct skl_module_cfg *mconfig,
7478c2ecf20Sopenharmony_ci			struct skl_algo_cfg *algo_mcfg)
7488c2ecf20Sopenharmony_ci{
7498c2ecf20Sopenharmony_ci	struct skl_base_cfg *base_cfg = (struct skl_base_cfg *)algo_mcfg;
7508c2ecf20Sopenharmony_ci
7518c2ecf20Sopenharmony_ci	skl_set_base_module_format(skl, mconfig, base_cfg);
7528c2ecf20Sopenharmony_ci
7538c2ecf20Sopenharmony_ci	if (mconfig->formats_config.caps_size == 0)
7548c2ecf20Sopenharmony_ci		return;
7558c2ecf20Sopenharmony_ci
7568c2ecf20Sopenharmony_ci	memcpy(algo_mcfg->params,
7578c2ecf20Sopenharmony_ci			mconfig->formats_config.caps,
7588c2ecf20Sopenharmony_ci			mconfig->formats_config.caps_size);
7598c2ecf20Sopenharmony_ci
7608c2ecf20Sopenharmony_ci}
7618c2ecf20Sopenharmony_ci
7628c2ecf20Sopenharmony_ci/*
7638c2ecf20Sopenharmony_ci * Mic select module allows selecting one or many input channels, thus
7648c2ecf20Sopenharmony_ci * acting as a demux.
7658c2ecf20Sopenharmony_ci *
7668c2ecf20Sopenharmony_ci * Mic select module take base module configuration and out-format
7678c2ecf20Sopenharmony_ci * configuration
7688c2ecf20Sopenharmony_ci */
7698c2ecf20Sopenharmony_cistatic void skl_set_base_outfmt_format(struct skl_dev *skl,
7708c2ecf20Sopenharmony_ci			struct skl_module_cfg *mconfig,
7718c2ecf20Sopenharmony_ci			struct skl_base_outfmt_cfg *base_outfmt_mcfg)
7728c2ecf20Sopenharmony_ci{
7738c2ecf20Sopenharmony_ci	struct skl_audio_data_format *out_fmt = &base_outfmt_mcfg->out_fmt;
7748c2ecf20Sopenharmony_ci	struct skl_base_cfg *base_cfg =
7758c2ecf20Sopenharmony_ci				(struct skl_base_cfg *)base_outfmt_mcfg;
7768c2ecf20Sopenharmony_ci
7778c2ecf20Sopenharmony_ci	skl_set_base_module_format(skl, mconfig, base_cfg);
7788c2ecf20Sopenharmony_ci	skl_setup_out_format(skl, mconfig, out_fmt);
7798c2ecf20Sopenharmony_ci}
7808c2ecf20Sopenharmony_ci
7818c2ecf20Sopenharmony_cistatic u16 skl_get_module_param_size(struct skl_dev *skl,
7828c2ecf20Sopenharmony_ci			struct skl_module_cfg *mconfig)
7838c2ecf20Sopenharmony_ci{
7848c2ecf20Sopenharmony_ci	u16 param_size;
7858c2ecf20Sopenharmony_ci
7868c2ecf20Sopenharmony_ci	switch (mconfig->m_type) {
7878c2ecf20Sopenharmony_ci	case SKL_MODULE_TYPE_COPIER:
7888c2ecf20Sopenharmony_ci		param_size = sizeof(struct skl_cpr_cfg);
7898c2ecf20Sopenharmony_ci		param_size += mconfig->formats_config.caps_size;
7908c2ecf20Sopenharmony_ci		return param_size;
7918c2ecf20Sopenharmony_ci
7928c2ecf20Sopenharmony_ci	case SKL_MODULE_TYPE_SRCINT:
7938c2ecf20Sopenharmony_ci		return sizeof(struct skl_src_module_cfg);
7948c2ecf20Sopenharmony_ci
7958c2ecf20Sopenharmony_ci	case SKL_MODULE_TYPE_UPDWMIX:
7968c2ecf20Sopenharmony_ci		return sizeof(struct skl_up_down_mixer_cfg);
7978c2ecf20Sopenharmony_ci
7988c2ecf20Sopenharmony_ci	case SKL_MODULE_TYPE_ALGO:
7998c2ecf20Sopenharmony_ci		param_size = sizeof(struct skl_base_cfg);
8008c2ecf20Sopenharmony_ci		param_size += mconfig->formats_config.caps_size;
8018c2ecf20Sopenharmony_ci		return param_size;
8028c2ecf20Sopenharmony_ci
8038c2ecf20Sopenharmony_ci	case SKL_MODULE_TYPE_BASE_OUTFMT:
8048c2ecf20Sopenharmony_ci	case SKL_MODULE_TYPE_MIC_SELECT:
8058c2ecf20Sopenharmony_ci		return sizeof(struct skl_base_outfmt_cfg);
8068c2ecf20Sopenharmony_ci
8078c2ecf20Sopenharmony_ci	case SKL_MODULE_TYPE_MIXER:
8088c2ecf20Sopenharmony_ci	case SKL_MODULE_TYPE_KPB:
8098c2ecf20Sopenharmony_ci		return sizeof(struct skl_base_cfg);
8108c2ecf20Sopenharmony_ci
8118c2ecf20Sopenharmony_ci	default:
8128c2ecf20Sopenharmony_ci		/*
8138c2ecf20Sopenharmony_ci		 * return only base cfg when no specific module type is
8148c2ecf20Sopenharmony_ci		 * specified
8158c2ecf20Sopenharmony_ci		 */
8168c2ecf20Sopenharmony_ci		return sizeof(struct skl_base_cfg);
8178c2ecf20Sopenharmony_ci	}
8188c2ecf20Sopenharmony_ci
8198c2ecf20Sopenharmony_ci	return 0;
8208c2ecf20Sopenharmony_ci}
8218c2ecf20Sopenharmony_ci
8228c2ecf20Sopenharmony_ci/*
8238c2ecf20Sopenharmony_ci * DSP firmware supports various modules like copier, SRC, updown etc.
8248c2ecf20Sopenharmony_ci * These modules required various parameters to be calculated and sent for
8258c2ecf20Sopenharmony_ci * the module initialization to DSP. By default a generic module needs only
8268c2ecf20Sopenharmony_ci * base module format configuration
8278c2ecf20Sopenharmony_ci */
8288c2ecf20Sopenharmony_ci
8298c2ecf20Sopenharmony_cistatic int skl_set_module_format(struct skl_dev *skl,
8308c2ecf20Sopenharmony_ci			struct skl_module_cfg *module_config,
8318c2ecf20Sopenharmony_ci			u16 *module_config_size,
8328c2ecf20Sopenharmony_ci			void **param_data)
8338c2ecf20Sopenharmony_ci{
8348c2ecf20Sopenharmony_ci	u16 param_size;
8358c2ecf20Sopenharmony_ci
8368c2ecf20Sopenharmony_ci	param_size  = skl_get_module_param_size(skl, module_config);
8378c2ecf20Sopenharmony_ci
8388c2ecf20Sopenharmony_ci	*param_data = kzalloc(param_size, GFP_KERNEL);
8398c2ecf20Sopenharmony_ci	if (NULL == *param_data)
8408c2ecf20Sopenharmony_ci		return -ENOMEM;
8418c2ecf20Sopenharmony_ci
8428c2ecf20Sopenharmony_ci	*module_config_size = param_size;
8438c2ecf20Sopenharmony_ci
8448c2ecf20Sopenharmony_ci	switch (module_config->m_type) {
8458c2ecf20Sopenharmony_ci	case SKL_MODULE_TYPE_COPIER:
8468c2ecf20Sopenharmony_ci		skl_set_copier_format(skl, module_config, *param_data);
8478c2ecf20Sopenharmony_ci		break;
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_ci	case SKL_MODULE_TYPE_SRCINT:
8508c2ecf20Sopenharmony_ci		skl_set_src_format(skl, module_config, *param_data);
8518c2ecf20Sopenharmony_ci		break;
8528c2ecf20Sopenharmony_ci
8538c2ecf20Sopenharmony_ci	case SKL_MODULE_TYPE_UPDWMIX:
8548c2ecf20Sopenharmony_ci		skl_set_updown_mixer_format(skl, module_config, *param_data);
8558c2ecf20Sopenharmony_ci		break;
8568c2ecf20Sopenharmony_ci
8578c2ecf20Sopenharmony_ci	case SKL_MODULE_TYPE_ALGO:
8588c2ecf20Sopenharmony_ci		skl_set_algo_format(skl, module_config, *param_data);
8598c2ecf20Sopenharmony_ci		break;
8608c2ecf20Sopenharmony_ci
8618c2ecf20Sopenharmony_ci	case SKL_MODULE_TYPE_BASE_OUTFMT:
8628c2ecf20Sopenharmony_ci	case SKL_MODULE_TYPE_MIC_SELECT:
8638c2ecf20Sopenharmony_ci		skl_set_base_outfmt_format(skl, module_config, *param_data);
8648c2ecf20Sopenharmony_ci		break;
8658c2ecf20Sopenharmony_ci
8668c2ecf20Sopenharmony_ci	case SKL_MODULE_TYPE_MIXER:
8678c2ecf20Sopenharmony_ci	case SKL_MODULE_TYPE_KPB:
8688c2ecf20Sopenharmony_ci		skl_set_base_module_format(skl, module_config, *param_data);
8698c2ecf20Sopenharmony_ci		break;
8708c2ecf20Sopenharmony_ci
8718c2ecf20Sopenharmony_ci	default:
8728c2ecf20Sopenharmony_ci		skl_set_base_module_format(skl, module_config, *param_data);
8738c2ecf20Sopenharmony_ci		break;
8748c2ecf20Sopenharmony_ci
8758c2ecf20Sopenharmony_ci	}
8768c2ecf20Sopenharmony_ci
8778c2ecf20Sopenharmony_ci	dev_dbg(skl->dev, "Module type=%d id=%d config size: %d bytes\n",
8788c2ecf20Sopenharmony_ci			module_config->m_type, module_config->id.module_id,
8798c2ecf20Sopenharmony_ci			param_size);
8808c2ecf20Sopenharmony_ci	print_hex_dump_debug("Module params:", DUMP_PREFIX_OFFSET, 8, 4,
8818c2ecf20Sopenharmony_ci			*param_data, param_size, false);
8828c2ecf20Sopenharmony_ci	return 0;
8838c2ecf20Sopenharmony_ci}
8848c2ecf20Sopenharmony_ci
8858c2ecf20Sopenharmony_cistatic int skl_get_queue_index(struct skl_module_pin *mpin,
8868c2ecf20Sopenharmony_ci				struct skl_module_inst_id id, int max)
8878c2ecf20Sopenharmony_ci{
8888c2ecf20Sopenharmony_ci	int i;
8898c2ecf20Sopenharmony_ci
8908c2ecf20Sopenharmony_ci	for (i = 0; i < max; i++)  {
8918c2ecf20Sopenharmony_ci		if (mpin[i].id.module_id == id.module_id &&
8928c2ecf20Sopenharmony_ci			mpin[i].id.instance_id == id.instance_id)
8938c2ecf20Sopenharmony_ci			return i;
8948c2ecf20Sopenharmony_ci	}
8958c2ecf20Sopenharmony_ci
8968c2ecf20Sopenharmony_ci	return -EINVAL;
8978c2ecf20Sopenharmony_ci}
8988c2ecf20Sopenharmony_ci
8998c2ecf20Sopenharmony_ci/*
9008c2ecf20Sopenharmony_ci * Allocates queue for each module.
9018c2ecf20Sopenharmony_ci * if dynamic, the pin_index is allocated 0 to max_pin.
9028c2ecf20Sopenharmony_ci * In static, the pin_index is fixed based on module_id and instance id
9038c2ecf20Sopenharmony_ci */
9048c2ecf20Sopenharmony_cistatic int skl_alloc_queue(struct skl_module_pin *mpin,
9058c2ecf20Sopenharmony_ci			struct skl_module_cfg *tgt_cfg, int max)
9068c2ecf20Sopenharmony_ci{
9078c2ecf20Sopenharmony_ci	int i;
9088c2ecf20Sopenharmony_ci	struct skl_module_inst_id id = tgt_cfg->id;
9098c2ecf20Sopenharmony_ci	/*
9108c2ecf20Sopenharmony_ci	 * if pin in dynamic, find first free pin
9118c2ecf20Sopenharmony_ci	 * otherwise find match module and instance id pin as topology will
9128c2ecf20Sopenharmony_ci	 * ensure a unique pin is assigned to this so no need to
9138c2ecf20Sopenharmony_ci	 * allocate/free
9148c2ecf20Sopenharmony_ci	 */
9158c2ecf20Sopenharmony_ci	for (i = 0; i < max; i++)  {
9168c2ecf20Sopenharmony_ci		if (mpin[i].is_dynamic) {
9178c2ecf20Sopenharmony_ci			if (!mpin[i].in_use &&
9188c2ecf20Sopenharmony_ci				mpin[i].pin_state == SKL_PIN_UNBIND) {
9198c2ecf20Sopenharmony_ci
9208c2ecf20Sopenharmony_ci				mpin[i].in_use = true;
9218c2ecf20Sopenharmony_ci				mpin[i].id.module_id = id.module_id;
9228c2ecf20Sopenharmony_ci				mpin[i].id.instance_id = id.instance_id;
9238c2ecf20Sopenharmony_ci				mpin[i].id.pvt_id = id.pvt_id;
9248c2ecf20Sopenharmony_ci				mpin[i].tgt_mcfg = tgt_cfg;
9258c2ecf20Sopenharmony_ci				return i;
9268c2ecf20Sopenharmony_ci			}
9278c2ecf20Sopenharmony_ci		} else {
9288c2ecf20Sopenharmony_ci			if (mpin[i].id.module_id == id.module_id &&
9298c2ecf20Sopenharmony_ci				mpin[i].id.instance_id == id.instance_id &&
9308c2ecf20Sopenharmony_ci				mpin[i].pin_state == SKL_PIN_UNBIND) {
9318c2ecf20Sopenharmony_ci
9328c2ecf20Sopenharmony_ci				mpin[i].tgt_mcfg = tgt_cfg;
9338c2ecf20Sopenharmony_ci				return i;
9348c2ecf20Sopenharmony_ci			}
9358c2ecf20Sopenharmony_ci		}
9368c2ecf20Sopenharmony_ci	}
9378c2ecf20Sopenharmony_ci
9388c2ecf20Sopenharmony_ci	return -EINVAL;
9398c2ecf20Sopenharmony_ci}
9408c2ecf20Sopenharmony_ci
9418c2ecf20Sopenharmony_cistatic void skl_free_queue(struct skl_module_pin *mpin, int q_index)
9428c2ecf20Sopenharmony_ci{
9438c2ecf20Sopenharmony_ci	if (mpin[q_index].is_dynamic) {
9448c2ecf20Sopenharmony_ci		mpin[q_index].in_use = false;
9458c2ecf20Sopenharmony_ci		mpin[q_index].id.module_id = 0;
9468c2ecf20Sopenharmony_ci		mpin[q_index].id.instance_id = 0;
9478c2ecf20Sopenharmony_ci		mpin[q_index].id.pvt_id = 0;
9488c2ecf20Sopenharmony_ci	}
9498c2ecf20Sopenharmony_ci	mpin[q_index].pin_state = SKL_PIN_UNBIND;
9508c2ecf20Sopenharmony_ci	mpin[q_index].tgt_mcfg = NULL;
9518c2ecf20Sopenharmony_ci}
9528c2ecf20Sopenharmony_ci
9538c2ecf20Sopenharmony_ci/* Module state will be set to unint, if all the out pin state is UNBIND */
9548c2ecf20Sopenharmony_ci
9558c2ecf20Sopenharmony_cistatic void skl_clear_module_state(struct skl_module_pin *mpin, int max,
9568c2ecf20Sopenharmony_ci						struct skl_module_cfg *mcfg)
9578c2ecf20Sopenharmony_ci{
9588c2ecf20Sopenharmony_ci	int i;
9598c2ecf20Sopenharmony_ci	bool found = false;
9608c2ecf20Sopenharmony_ci
9618c2ecf20Sopenharmony_ci	for (i = 0; i < max; i++)  {
9628c2ecf20Sopenharmony_ci		if (mpin[i].pin_state == SKL_PIN_UNBIND)
9638c2ecf20Sopenharmony_ci			continue;
9648c2ecf20Sopenharmony_ci		found = true;
9658c2ecf20Sopenharmony_ci		break;
9668c2ecf20Sopenharmony_ci	}
9678c2ecf20Sopenharmony_ci
9688c2ecf20Sopenharmony_ci	if (!found)
9698c2ecf20Sopenharmony_ci		mcfg->m_state = SKL_MODULE_INIT_DONE;
9708c2ecf20Sopenharmony_ci	return;
9718c2ecf20Sopenharmony_ci}
9728c2ecf20Sopenharmony_ci
9738c2ecf20Sopenharmony_ci/*
9748c2ecf20Sopenharmony_ci * A module needs to be instanataited in DSP. A mdoule is present in a
9758c2ecf20Sopenharmony_ci * collection of module referred as a PIPE.
9768c2ecf20Sopenharmony_ci * We first calculate the module format, based on module type and then
9778c2ecf20Sopenharmony_ci * invoke the DSP by sending IPC INIT_INSTANCE using ipc helper
9788c2ecf20Sopenharmony_ci */
9798c2ecf20Sopenharmony_ciint skl_init_module(struct skl_dev *skl,
9808c2ecf20Sopenharmony_ci			struct skl_module_cfg *mconfig)
9818c2ecf20Sopenharmony_ci{
9828c2ecf20Sopenharmony_ci	u16 module_config_size = 0;
9838c2ecf20Sopenharmony_ci	void *param_data = NULL;
9848c2ecf20Sopenharmony_ci	int ret;
9858c2ecf20Sopenharmony_ci	struct skl_ipc_init_instance_msg msg;
9868c2ecf20Sopenharmony_ci
9878c2ecf20Sopenharmony_ci	dev_dbg(skl->dev, "%s: module_id = %d instance=%d\n", __func__,
9888c2ecf20Sopenharmony_ci		 mconfig->id.module_id, mconfig->id.pvt_id);
9898c2ecf20Sopenharmony_ci
9908c2ecf20Sopenharmony_ci	if (mconfig->pipe->state != SKL_PIPE_CREATED) {
9918c2ecf20Sopenharmony_ci		dev_err(skl->dev, "Pipe not created state= %d pipe_id= %d\n",
9928c2ecf20Sopenharmony_ci				 mconfig->pipe->state, mconfig->pipe->ppl_id);
9938c2ecf20Sopenharmony_ci		return -EIO;
9948c2ecf20Sopenharmony_ci	}
9958c2ecf20Sopenharmony_ci
9968c2ecf20Sopenharmony_ci	ret = skl_set_module_format(skl, mconfig,
9978c2ecf20Sopenharmony_ci			&module_config_size, &param_data);
9988c2ecf20Sopenharmony_ci	if (ret < 0) {
9998c2ecf20Sopenharmony_ci		dev_err(skl->dev, "Failed to set module format ret=%d\n", ret);
10008c2ecf20Sopenharmony_ci		return ret;
10018c2ecf20Sopenharmony_ci	}
10028c2ecf20Sopenharmony_ci
10038c2ecf20Sopenharmony_ci	msg.module_id = mconfig->id.module_id;
10048c2ecf20Sopenharmony_ci	msg.instance_id = mconfig->id.pvt_id;
10058c2ecf20Sopenharmony_ci	msg.ppl_instance_id = mconfig->pipe->ppl_id;
10068c2ecf20Sopenharmony_ci	msg.param_data_size = module_config_size;
10078c2ecf20Sopenharmony_ci	msg.core_id = mconfig->core_id;
10088c2ecf20Sopenharmony_ci	msg.domain = mconfig->domain;
10098c2ecf20Sopenharmony_ci
10108c2ecf20Sopenharmony_ci	ret = skl_ipc_init_instance(&skl->ipc, &msg, param_data);
10118c2ecf20Sopenharmony_ci	if (ret < 0) {
10128c2ecf20Sopenharmony_ci		dev_err(skl->dev, "Failed to init instance ret=%d\n", ret);
10138c2ecf20Sopenharmony_ci		kfree(param_data);
10148c2ecf20Sopenharmony_ci		return ret;
10158c2ecf20Sopenharmony_ci	}
10168c2ecf20Sopenharmony_ci	mconfig->m_state = SKL_MODULE_INIT_DONE;
10178c2ecf20Sopenharmony_ci	kfree(param_data);
10188c2ecf20Sopenharmony_ci	return ret;
10198c2ecf20Sopenharmony_ci}
10208c2ecf20Sopenharmony_ci
10218c2ecf20Sopenharmony_cistatic void skl_dump_bind_info(struct skl_dev *skl, struct skl_module_cfg
10228c2ecf20Sopenharmony_ci	*src_module, struct skl_module_cfg *dst_module)
10238c2ecf20Sopenharmony_ci{
10248c2ecf20Sopenharmony_ci	dev_dbg(skl->dev, "%s: src module_id = %d  src_instance=%d\n",
10258c2ecf20Sopenharmony_ci		__func__, src_module->id.module_id, src_module->id.pvt_id);
10268c2ecf20Sopenharmony_ci	dev_dbg(skl->dev, "%s: dst_module=%d dst_instance=%d\n", __func__,
10278c2ecf20Sopenharmony_ci		 dst_module->id.module_id, dst_module->id.pvt_id);
10288c2ecf20Sopenharmony_ci
10298c2ecf20Sopenharmony_ci	dev_dbg(skl->dev, "src_module state = %d dst module state = %d\n",
10308c2ecf20Sopenharmony_ci		src_module->m_state, dst_module->m_state);
10318c2ecf20Sopenharmony_ci}
10328c2ecf20Sopenharmony_ci
10338c2ecf20Sopenharmony_ci/*
10348c2ecf20Sopenharmony_ci * On module freeup, we need to unbind the module with modules
10358c2ecf20Sopenharmony_ci * it is already bind.
10368c2ecf20Sopenharmony_ci * Find the pin allocated and unbind then using bind_unbind IPC
10378c2ecf20Sopenharmony_ci */
10388c2ecf20Sopenharmony_ciint skl_unbind_modules(struct skl_dev *skl,
10398c2ecf20Sopenharmony_ci			struct skl_module_cfg *src_mcfg,
10408c2ecf20Sopenharmony_ci			struct skl_module_cfg *dst_mcfg)
10418c2ecf20Sopenharmony_ci{
10428c2ecf20Sopenharmony_ci	int ret;
10438c2ecf20Sopenharmony_ci	struct skl_ipc_bind_unbind_msg msg;
10448c2ecf20Sopenharmony_ci	struct skl_module_inst_id src_id = src_mcfg->id;
10458c2ecf20Sopenharmony_ci	struct skl_module_inst_id dst_id = dst_mcfg->id;
10468c2ecf20Sopenharmony_ci	int in_max = dst_mcfg->module->max_input_pins;
10478c2ecf20Sopenharmony_ci	int out_max = src_mcfg->module->max_output_pins;
10488c2ecf20Sopenharmony_ci	int src_index, dst_index, src_pin_state, dst_pin_state;
10498c2ecf20Sopenharmony_ci
10508c2ecf20Sopenharmony_ci	skl_dump_bind_info(skl, src_mcfg, dst_mcfg);
10518c2ecf20Sopenharmony_ci
10528c2ecf20Sopenharmony_ci	/* get src queue index */
10538c2ecf20Sopenharmony_ci	src_index = skl_get_queue_index(src_mcfg->m_out_pin, dst_id, out_max);
10548c2ecf20Sopenharmony_ci	if (src_index < 0)
10558c2ecf20Sopenharmony_ci		return 0;
10568c2ecf20Sopenharmony_ci
10578c2ecf20Sopenharmony_ci	msg.src_queue = src_index;
10588c2ecf20Sopenharmony_ci
10598c2ecf20Sopenharmony_ci	/* get dst queue index */
10608c2ecf20Sopenharmony_ci	dst_index  = skl_get_queue_index(dst_mcfg->m_in_pin, src_id, in_max);
10618c2ecf20Sopenharmony_ci	if (dst_index < 0)
10628c2ecf20Sopenharmony_ci		return 0;
10638c2ecf20Sopenharmony_ci
10648c2ecf20Sopenharmony_ci	msg.dst_queue = dst_index;
10658c2ecf20Sopenharmony_ci
10668c2ecf20Sopenharmony_ci	src_pin_state = src_mcfg->m_out_pin[src_index].pin_state;
10678c2ecf20Sopenharmony_ci	dst_pin_state = dst_mcfg->m_in_pin[dst_index].pin_state;
10688c2ecf20Sopenharmony_ci
10698c2ecf20Sopenharmony_ci	if (src_pin_state != SKL_PIN_BIND_DONE ||
10708c2ecf20Sopenharmony_ci		dst_pin_state != SKL_PIN_BIND_DONE)
10718c2ecf20Sopenharmony_ci		return 0;
10728c2ecf20Sopenharmony_ci
10738c2ecf20Sopenharmony_ci	msg.module_id = src_mcfg->id.module_id;
10748c2ecf20Sopenharmony_ci	msg.instance_id = src_mcfg->id.pvt_id;
10758c2ecf20Sopenharmony_ci	msg.dst_module_id = dst_mcfg->id.module_id;
10768c2ecf20Sopenharmony_ci	msg.dst_instance_id = dst_mcfg->id.pvt_id;
10778c2ecf20Sopenharmony_ci	msg.bind = false;
10788c2ecf20Sopenharmony_ci
10798c2ecf20Sopenharmony_ci	ret = skl_ipc_bind_unbind(&skl->ipc, &msg);
10808c2ecf20Sopenharmony_ci	if (!ret) {
10818c2ecf20Sopenharmony_ci		/* free queue only if unbind is success */
10828c2ecf20Sopenharmony_ci		skl_free_queue(src_mcfg->m_out_pin, src_index);
10838c2ecf20Sopenharmony_ci		skl_free_queue(dst_mcfg->m_in_pin, dst_index);
10848c2ecf20Sopenharmony_ci
10858c2ecf20Sopenharmony_ci		/*
10868c2ecf20Sopenharmony_ci		 * check only if src module bind state, bind is
10878c2ecf20Sopenharmony_ci		 * always from src -> sink
10888c2ecf20Sopenharmony_ci		 */
10898c2ecf20Sopenharmony_ci		skl_clear_module_state(src_mcfg->m_out_pin, out_max, src_mcfg);
10908c2ecf20Sopenharmony_ci	}
10918c2ecf20Sopenharmony_ci
10928c2ecf20Sopenharmony_ci	return ret;
10938c2ecf20Sopenharmony_ci}
10948c2ecf20Sopenharmony_ci
10958c2ecf20Sopenharmony_cistatic void fill_pin_params(struct skl_audio_data_format *pin_fmt,
10968c2ecf20Sopenharmony_ci				struct skl_module_fmt *format)
10978c2ecf20Sopenharmony_ci{
10988c2ecf20Sopenharmony_ci	pin_fmt->number_of_channels = format->channels;
10998c2ecf20Sopenharmony_ci	pin_fmt->s_freq = format->s_freq;
11008c2ecf20Sopenharmony_ci	pin_fmt->bit_depth = format->bit_depth;
11018c2ecf20Sopenharmony_ci	pin_fmt->valid_bit_depth = format->valid_bit_depth;
11028c2ecf20Sopenharmony_ci	pin_fmt->ch_cfg = format->ch_cfg;
11038c2ecf20Sopenharmony_ci	pin_fmt->sample_type = format->sample_type;
11048c2ecf20Sopenharmony_ci	pin_fmt->channel_map = format->ch_map;
11058c2ecf20Sopenharmony_ci	pin_fmt->interleaving = format->interleaving_style;
11068c2ecf20Sopenharmony_ci}
11078c2ecf20Sopenharmony_ci
11088c2ecf20Sopenharmony_ci#define CPR_SINK_FMT_PARAM_ID 2
11098c2ecf20Sopenharmony_ci
11108c2ecf20Sopenharmony_ci/*
11118c2ecf20Sopenharmony_ci * Once a module is instantiated it need to be 'bind' with other modules in
11128c2ecf20Sopenharmony_ci * the pipeline. For binding we need to find the module pins which are bind
11138c2ecf20Sopenharmony_ci * together
11148c2ecf20Sopenharmony_ci * This function finds the pins and then sends bund_unbind IPC message to
11158c2ecf20Sopenharmony_ci * DSP using IPC helper
11168c2ecf20Sopenharmony_ci */
11178c2ecf20Sopenharmony_ciint skl_bind_modules(struct skl_dev *skl,
11188c2ecf20Sopenharmony_ci			struct skl_module_cfg *src_mcfg,
11198c2ecf20Sopenharmony_ci			struct skl_module_cfg *dst_mcfg)
11208c2ecf20Sopenharmony_ci{
11218c2ecf20Sopenharmony_ci	int ret = 0;
11228c2ecf20Sopenharmony_ci	struct skl_ipc_bind_unbind_msg msg;
11238c2ecf20Sopenharmony_ci	int in_max = dst_mcfg->module->max_input_pins;
11248c2ecf20Sopenharmony_ci	int out_max = src_mcfg->module->max_output_pins;
11258c2ecf20Sopenharmony_ci	int src_index, dst_index;
11268c2ecf20Sopenharmony_ci	struct skl_module_fmt *format;
11278c2ecf20Sopenharmony_ci	struct skl_cpr_pin_fmt pin_fmt;
11288c2ecf20Sopenharmony_ci	struct skl_module *module;
11298c2ecf20Sopenharmony_ci	struct skl_module_iface *fmt;
11308c2ecf20Sopenharmony_ci
11318c2ecf20Sopenharmony_ci	skl_dump_bind_info(skl, src_mcfg, dst_mcfg);
11328c2ecf20Sopenharmony_ci
11338c2ecf20Sopenharmony_ci	if (src_mcfg->m_state < SKL_MODULE_INIT_DONE ||
11348c2ecf20Sopenharmony_ci		dst_mcfg->m_state < SKL_MODULE_INIT_DONE)
11358c2ecf20Sopenharmony_ci		return 0;
11368c2ecf20Sopenharmony_ci
11378c2ecf20Sopenharmony_ci	src_index = skl_alloc_queue(src_mcfg->m_out_pin, dst_mcfg, out_max);
11388c2ecf20Sopenharmony_ci	if (src_index < 0)
11398c2ecf20Sopenharmony_ci		return -EINVAL;
11408c2ecf20Sopenharmony_ci
11418c2ecf20Sopenharmony_ci	msg.src_queue = src_index;
11428c2ecf20Sopenharmony_ci	dst_index = skl_alloc_queue(dst_mcfg->m_in_pin, src_mcfg, in_max);
11438c2ecf20Sopenharmony_ci	if (dst_index < 0) {
11448c2ecf20Sopenharmony_ci		skl_free_queue(src_mcfg->m_out_pin, src_index);
11458c2ecf20Sopenharmony_ci		return -EINVAL;
11468c2ecf20Sopenharmony_ci	}
11478c2ecf20Sopenharmony_ci
11488c2ecf20Sopenharmony_ci	/*
11498c2ecf20Sopenharmony_ci	 * Copier module requires the separate large_config_set_ipc to
11508c2ecf20Sopenharmony_ci	 * configure the pins other than 0
11518c2ecf20Sopenharmony_ci	 */
11528c2ecf20Sopenharmony_ci	if (src_mcfg->m_type == SKL_MODULE_TYPE_COPIER && src_index > 0) {
11538c2ecf20Sopenharmony_ci		pin_fmt.sink_id = src_index;
11548c2ecf20Sopenharmony_ci		module = src_mcfg->module;
11558c2ecf20Sopenharmony_ci		fmt = &module->formats[src_mcfg->fmt_idx];
11568c2ecf20Sopenharmony_ci
11578c2ecf20Sopenharmony_ci		/* Input fmt is same as that of src module input cfg */
11588c2ecf20Sopenharmony_ci		format = &fmt->inputs[0].fmt;
11598c2ecf20Sopenharmony_ci		fill_pin_params(&(pin_fmt.src_fmt), format);
11608c2ecf20Sopenharmony_ci
11618c2ecf20Sopenharmony_ci		format = &fmt->outputs[src_index].fmt;
11628c2ecf20Sopenharmony_ci		fill_pin_params(&(pin_fmt.dst_fmt), format);
11638c2ecf20Sopenharmony_ci		ret = skl_set_module_params(skl, (void *)&pin_fmt,
11648c2ecf20Sopenharmony_ci					sizeof(struct skl_cpr_pin_fmt),
11658c2ecf20Sopenharmony_ci					CPR_SINK_FMT_PARAM_ID, src_mcfg);
11668c2ecf20Sopenharmony_ci
11678c2ecf20Sopenharmony_ci		if (ret < 0)
11688c2ecf20Sopenharmony_ci			goto out;
11698c2ecf20Sopenharmony_ci	}
11708c2ecf20Sopenharmony_ci
11718c2ecf20Sopenharmony_ci	msg.dst_queue = dst_index;
11728c2ecf20Sopenharmony_ci
11738c2ecf20Sopenharmony_ci	dev_dbg(skl->dev, "src queue = %d dst queue =%d\n",
11748c2ecf20Sopenharmony_ci			 msg.src_queue, msg.dst_queue);
11758c2ecf20Sopenharmony_ci
11768c2ecf20Sopenharmony_ci	msg.module_id = src_mcfg->id.module_id;
11778c2ecf20Sopenharmony_ci	msg.instance_id = src_mcfg->id.pvt_id;
11788c2ecf20Sopenharmony_ci	msg.dst_module_id = dst_mcfg->id.module_id;
11798c2ecf20Sopenharmony_ci	msg.dst_instance_id = dst_mcfg->id.pvt_id;
11808c2ecf20Sopenharmony_ci	msg.bind = true;
11818c2ecf20Sopenharmony_ci
11828c2ecf20Sopenharmony_ci	ret = skl_ipc_bind_unbind(&skl->ipc, &msg);
11838c2ecf20Sopenharmony_ci
11848c2ecf20Sopenharmony_ci	if (!ret) {
11858c2ecf20Sopenharmony_ci		src_mcfg->m_state = SKL_MODULE_BIND_DONE;
11868c2ecf20Sopenharmony_ci		src_mcfg->m_out_pin[src_index].pin_state = SKL_PIN_BIND_DONE;
11878c2ecf20Sopenharmony_ci		dst_mcfg->m_in_pin[dst_index].pin_state = SKL_PIN_BIND_DONE;
11888c2ecf20Sopenharmony_ci		return ret;
11898c2ecf20Sopenharmony_ci	}
11908c2ecf20Sopenharmony_ciout:
11918c2ecf20Sopenharmony_ci	/* error case , if IPC fails, clear the queue index */
11928c2ecf20Sopenharmony_ci	skl_free_queue(src_mcfg->m_out_pin, src_index);
11938c2ecf20Sopenharmony_ci	skl_free_queue(dst_mcfg->m_in_pin, dst_index);
11948c2ecf20Sopenharmony_ci
11958c2ecf20Sopenharmony_ci	return ret;
11968c2ecf20Sopenharmony_ci}
11978c2ecf20Sopenharmony_ci
11988c2ecf20Sopenharmony_cistatic int skl_set_pipe_state(struct skl_dev *skl, struct skl_pipe *pipe,
11998c2ecf20Sopenharmony_ci	enum skl_ipc_pipeline_state state)
12008c2ecf20Sopenharmony_ci{
12018c2ecf20Sopenharmony_ci	dev_dbg(skl->dev, "%s: pipe_state = %d\n", __func__, state);
12028c2ecf20Sopenharmony_ci
12038c2ecf20Sopenharmony_ci	return skl_ipc_set_pipeline_state(&skl->ipc, pipe->ppl_id, state);
12048c2ecf20Sopenharmony_ci}
12058c2ecf20Sopenharmony_ci
12068c2ecf20Sopenharmony_ci/*
12078c2ecf20Sopenharmony_ci * A pipeline is a collection of modules. Before a module in instantiated a
12088c2ecf20Sopenharmony_ci * pipeline needs to be created for it.
12098c2ecf20Sopenharmony_ci * This function creates pipeline, by sending create pipeline IPC messages
12108c2ecf20Sopenharmony_ci * to FW
12118c2ecf20Sopenharmony_ci */
12128c2ecf20Sopenharmony_ciint skl_create_pipeline(struct skl_dev *skl, struct skl_pipe *pipe)
12138c2ecf20Sopenharmony_ci{
12148c2ecf20Sopenharmony_ci	int ret;
12158c2ecf20Sopenharmony_ci
12168c2ecf20Sopenharmony_ci	dev_dbg(skl->dev, "%s: pipe_id = %d\n", __func__, pipe->ppl_id);
12178c2ecf20Sopenharmony_ci
12188c2ecf20Sopenharmony_ci	ret = skl_ipc_create_pipeline(&skl->ipc, pipe->memory_pages,
12198c2ecf20Sopenharmony_ci				pipe->pipe_priority, pipe->ppl_id,
12208c2ecf20Sopenharmony_ci				pipe->lp_mode);
12218c2ecf20Sopenharmony_ci	if (ret < 0) {
12228c2ecf20Sopenharmony_ci		dev_err(skl->dev, "Failed to create pipeline\n");
12238c2ecf20Sopenharmony_ci		return ret;
12248c2ecf20Sopenharmony_ci	}
12258c2ecf20Sopenharmony_ci
12268c2ecf20Sopenharmony_ci	pipe->state = SKL_PIPE_CREATED;
12278c2ecf20Sopenharmony_ci
12288c2ecf20Sopenharmony_ci	return 0;
12298c2ecf20Sopenharmony_ci}
12308c2ecf20Sopenharmony_ci
12318c2ecf20Sopenharmony_ci/*
12328c2ecf20Sopenharmony_ci * A pipeline needs to be deleted on cleanup. If a pipeline is running,
12338c2ecf20Sopenharmony_ci * then pause it first. Before actual deletion, pipeline should enter
12348c2ecf20Sopenharmony_ci * reset state. Finish the procedure by sending delete pipeline IPC.
12358c2ecf20Sopenharmony_ci * DSP will stop the DMA engines and release resources
12368c2ecf20Sopenharmony_ci */
12378c2ecf20Sopenharmony_ciint skl_delete_pipe(struct skl_dev *skl, struct skl_pipe *pipe)
12388c2ecf20Sopenharmony_ci{
12398c2ecf20Sopenharmony_ci	int ret;
12408c2ecf20Sopenharmony_ci
12418c2ecf20Sopenharmony_ci	dev_dbg(skl->dev, "%s: pipe = %d\n", __func__, pipe->ppl_id);
12428c2ecf20Sopenharmony_ci
12438c2ecf20Sopenharmony_ci	/* If pipe was not created in FW, do not try to delete it */
12448c2ecf20Sopenharmony_ci	if (pipe->state < SKL_PIPE_CREATED)
12458c2ecf20Sopenharmony_ci		return 0;
12468c2ecf20Sopenharmony_ci
12478c2ecf20Sopenharmony_ci	/* If pipe is started, do stop the pipe in FW. */
12488c2ecf20Sopenharmony_ci	if (pipe->state >= SKL_PIPE_STARTED) {
12498c2ecf20Sopenharmony_ci		ret = skl_set_pipe_state(skl, pipe, PPL_PAUSED);
12508c2ecf20Sopenharmony_ci		if (ret < 0) {
12518c2ecf20Sopenharmony_ci			dev_err(skl->dev, "Failed to stop pipeline\n");
12528c2ecf20Sopenharmony_ci			return ret;
12538c2ecf20Sopenharmony_ci		}
12548c2ecf20Sopenharmony_ci
12558c2ecf20Sopenharmony_ci		pipe->state = SKL_PIPE_PAUSED;
12568c2ecf20Sopenharmony_ci	}
12578c2ecf20Sopenharmony_ci
12588c2ecf20Sopenharmony_ci	/* reset pipe state before deletion */
12598c2ecf20Sopenharmony_ci	ret = skl_set_pipe_state(skl, pipe, PPL_RESET);
12608c2ecf20Sopenharmony_ci	if (ret < 0) {
12618c2ecf20Sopenharmony_ci		dev_err(skl->dev, "Failed to reset pipe ret=%d\n", ret);
12628c2ecf20Sopenharmony_ci		return ret;
12638c2ecf20Sopenharmony_ci	}
12648c2ecf20Sopenharmony_ci
12658c2ecf20Sopenharmony_ci	pipe->state = SKL_PIPE_RESET;
12668c2ecf20Sopenharmony_ci
12678c2ecf20Sopenharmony_ci	ret = skl_ipc_delete_pipeline(&skl->ipc, pipe->ppl_id);
12688c2ecf20Sopenharmony_ci	if (ret < 0) {
12698c2ecf20Sopenharmony_ci		dev_err(skl->dev, "Failed to delete pipeline\n");
12708c2ecf20Sopenharmony_ci		return ret;
12718c2ecf20Sopenharmony_ci	}
12728c2ecf20Sopenharmony_ci
12738c2ecf20Sopenharmony_ci	pipe->state = SKL_PIPE_INVALID;
12748c2ecf20Sopenharmony_ci
12758c2ecf20Sopenharmony_ci	return ret;
12768c2ecf20Sopenharmony_ci}
12778c2ecf20Sopenharmony_ci
12788c2ecf20Sopenharmony_ci/*
12798c2ecf20Sopenharmony_ci * A pipeline is also a scheduling entity in DSP which can be run, stopped
12808c2ecf20Sopenharmony_ci * For processing data the pipe need to be run by sending IPC set pipe state
12818c2ecf20Sopenharmony_ci * to DSP
12828c2ecf20Sopenharmony_ci */
12838c2ecf20Sopenharmony_ciint skl_run_pipe(struct skl_dev *skl, struct skl_pipe *pipe)
12848c2ecf20Sopenharmony_ci{
12858c2ecf20Sopenharmony_ci	int ret;
12868c2ecf20Sopenharmony_ci
12878c2ecf20Sopenharmony_ci	dev_dbg(skl->dev, "%s: pipe = %d\n", __func__, pipe->ppl_id);
12888c2ecf20Sopenharmony_ci
12898c2ecf20Sopenharmony_ci	/* If pipe was not created in FW, do not try to pause or delete */
12908c2ecf20Sopenharmony_ci	if (pipe->state < SKL_PIPE_CREATED)
12918c2ecf20Sopenharmony_ci		return 0;
12928c2ecf20Sopenharmony_ci
12938c2ecf20Sopenharmony_ci	/* Pipe has to be paused before it is started */
12948c2ecf20Sopenharmony_ci	ret = skl_set_pipe_state(skl, pipe, PPL_PAUSED);
12958c2ecf20Sopenharmony_ci	if (ret < 0) {
12968c2ecf20Sopenharmony_ci		dev_err(skl->dev, "Failed to pause pipe\n");
12978c2ecf20Sopenharmony_ci		return ret;
12988c2ecf20Sopenharmony_ci	}
12998c2ecf20Sopenharmony_ci
13008c2ecf20Sopenharmony_ci	pipe->state = SKL_PIPE_PAUSED;
13018c2ecf20Sopenharmony_ci
13028c2ecf20Sopenharmony_ci	ret = skl_set_pipe_state(skl, pipe, PPL_RUNNING);
13038c2ecf20Sopenharmony_ci	if (ret < 0) {
13048c2ecf20Sopenharmony_ci		dev_err(skl->dev, "Failed to start pipe\n");
13058c2ecf20Sopenharmony_ci		return ret;
13068c2ecf20Sopenharmony_ci	}
13078c2ecf20Sopenharmony_ci
13088c2ecf20Sopenharmony_ci	pipe->state = SKL_PIPE_STARTED;
13098c2ecf20Sopenharmony_ci
13108c2ecf20Sopenharmony_ci	return 0;
13118c2ecf20Sopenharmony_ci}
13128c2ecf20Sopenharmony_ci
13138c2ecf20Sopenharmony_ci/*
13148c2ecf20Sopenharmony_ci * Stop the pipeline by sending set pipe state IPC
13158c2ecf20Sopenharmony_ci * DSP doesnt implement stop so we always send pause message
13168c2ecf20Sopenharmony_ci */
13178c2ecf20Sopenharmony_ciint skl_stop_pipe(struct skl_dev *skl, struct skl_pipe *pipe)
13188c2ecf20Sopenharmony_ci{
13198c2ecf20Sopenharmony_ci	int ret;
13208c2ecf20Sopenharmony_ci
13218c2ecf20Sopenharmony_ci	dev_dbg(skl->dev, "In %s pipe=%d\n", __func__, pipe->ppl_id);
13228c2ecf20Sopenharmony_ci
13238c2ecf20Sopenharmony_ci	/* If pipe was not created in FW, do not try to pause or delete */
13248c2ecf20Sopenharmony_ci	if (pipe->state < SKL_PIPE_PAUSED)
13258c2ecf20Sopenharmony_ci		return 0;
13268c2ecf20Sopenharmony_ci
13278c2ecf20Sopenharmony_ci	ret = skl_set_pipe_state(skl, pipe, PPL_PAUSED);
13288c2ecf20Sopenharmony_ci	if (ret < 0) {
13298c2ecf20Sopenharmony_ci		dev_dbg(skl->dev, "Failed to stop pipe\n");
13308c2ecf20Sopenharmony_ci		return ret;
13318c2ecf20Sopenharmony_ci	}
13328c2ecf20Sopenharmony_ci
13338c2ecf20Sopenharmony_ci	pipe->state = SKL_PIPE_PAUSED;
13348c2ecf20Sopenharmony_ci
13358c2ecf20Sopenharmony_ci	return 0;
13368c2ecf20Sopenharmony_ci}
13378c2ecf20Sopenharmony_ci
13388c2ecf20Sopenharmony_ci/*
13398c2ecf20Sopenharmony_ci * Reset the pipeline by sending set pipe state IPC this will reset the DMA
13408c2ecf20Sopenharmony_ci * from the DSP side
13418c2ecf20Sopenharmony_ci */
13428c2ecf20Sopenharmony_ciint skl_reset_pipe(struct skl_dev *skl, struct skl_pipe *pipe)
13438c2ecf20Sopenharmony_ci{
13448c2ecf20Sopenharmony_ci	int ret;
13458c2ecf20Sopenharmony_ci
13468c2ecf20Sopenharmony_ci	/* If pipe was not created in FW, do not try to pause or delete */
13478c2ecf20Sopenharmony_ci	if (pipe->state < SKL_PIPE_PAUSED)
13488c2ecf20Sopenharmony_ci		return 0;
13498c2ecf20Sopenharmony_ci
13508c2ecf20Sopenharmony_ci	ret = skl_set_pipe_state(skl, pipe, PPL_RESET);
13518c2ecf20Sopenharmony_ci	if (ret < 0) {
13528c2ecf20Sopenharmony_ci		dev_dbg(skl->dev, "Failed to reset pipe ret=%d\n", ret);
13538c2ecf20Sopenharmony_ci		return ret;
13548c2ecf20Sopenharmony_ci	}
13558c2ecf20Sopenharmony_ci
13568c2ecf20Sopenharmony_ci	pipe->state = SKL_PIPE_RESET;
13578c2ecf20Sopenharmony_ci
13588c2ecf20Sopenharmony_ci	return 0;
13598c2ecf20Sopenharmony_ci}
13608c2ecf20Sopenharmony_ci
13618c2ecf20Sopenharmony_ci/* Algo parameter set helper function */
13628c2ecf20Sopenharmony_ciint skl_set_module_params(struct skl_dev *skl, u32 *params, int size,
13638c2ecf20Sopenharmony_ci				u32 param_id, struct skl_module_cfg *mcfg)
13648c2ecf20Sopenharmony_ci{
13658c2ecf20Sopenharmony_ci	struct skl_ipc_large_config_msg msg;
13668c2ecf20Sopenharmony_ci
13678c2ecf20Sopenharmony_ci	msg.module_id = mcfg->id.module_id;
13688c2ecf20Sopenharmony_ci	msg.instance_id = mcfg->id.pvt_id;
13698c2ecf20Sopenharmony_ci	msg.param_data_size = size;
13708c2ecf20Sopenharmony_ci	msg.large_param_id = param_id;
13718c2ecf20Sopenharmony_ci
13728c2ecf20Sopenharmony_ci	return skl_ipc_set_large_config(&skl->ipc, &msg, params);
13738c2ecf20Sopenharmony_ci}
13748c2ecf20Sopenharmony_ci
13758c2ecf20Sopenharmony_ciint skl_get_module_params(struct skl_dev *skl, u32 *params, int size,
13768c2ecf20Sopenharmony_ci			  u32 param_id, struct skl_module_cfg *mcfg)
13778c2ecf20Sopenharmony_ci{
13788c2ecf20Sopenharmony_ci	struct skl_ipc_large_config_msg msg;
13798c2ecf20Sopenharmony_ci	size_t bytes = size;
13808c2ecf20Sopenharmony_ci
13818c2ecf20Sopenharmony_ci	msg.module_id = mcfg->id.module_id;
13828c2ecf20Sopenharmony_ci	msg.instance_id = mcfg->id.pvt_id;
13838c2ecf20Sopenharmony_ci	msg.param_data_size = size;
13848c2ecf20Sopenharmony_ci	msg.large_param_id = param_id;
13858c2ecf20Sopenharmony_ci
13868c2ecf20Sopenharmony_ci	return skl_ipc_get_large_config(&skl->ipc, &msg, &params, &bytes);
13878c2ecf20Sopenharmony_ci}
1388