1d255b095SJeeja KP /* 2d255b095SJeeja KP * skl-message.c - HDA DSP interface for FW registration, Pipe and Module 3d255b095SJeeja KP * configurations 4d255b095SJeeja KP * 5d255b095SJeeja KP * Copyright (C) 2015 Intel Corp 6d255b095SJeeja KP * Author:Rafal Redzimski <rafal.f.redzimski@intel.com> 7d255b095SJeeja KP * Jeeja KP <jeeja.kp@intel.com> 8d255b095SJeeja KP * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 9d255b095SJeeja KP * 10d255b095SJeeja KP * This program is free software; you can redistribute it and/or modify 11d255b095SJeeja KP * it under the terms of the GNU General Public License as version 2, as 12d255b095SJeeja KP * published by the Free Software Foundation. 13d255b095SJeeja KP * 14d255b095SJeeja KP * This program is distributed in the hope that it will be useful, but 15d255b095SJeeja KP * WITHOUT ANY WARRANTY; without even the implied warranty of 16d255b095SJeeja KP * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17d255b095SJeeja KP * General Public License for more details. 18d255b095SJeeja KP */ 19d255b095SJeeja KP 20d255b095SJeeja KP #include <linux/slab.h> 21d255b095SJeeja KP #include <linux/pci.h> 22d255b095SJeeja KP #include <sound/core.h> 23d255b095SJeeja KP #include <sound/pcm.h> 24d255b095SJeeja KP #include "skl-sst-dsp.h" 25d255b095SJeeja KP #include "skl-sst-ipc.h" 26d255b095SJeeja KP #include "skl.h" 27d255b095SJeeja KP #include "../common/sst-dsp.h" 28d255b095SJeeja KP #include "../common/sst-dsp-priv.h" 2923db472bSJeeja KP #include "skl-topology.h" 3023db472bSJeeja KP #include "skl-tplg-interface.h" 31d255b095SJeeja KP 32d255b095SJeeja KP static int skl_alloc_dma_buf(struct device *dev, 33d255b095SJeeja KP struct snd_dma_buffer *dmab, size_t size) 34d255b095SJeeja KP { 35d255b095SJeeja KP struct hdac_ext_bus *ebus = dev_get_drvdata(dev); 36d255b095SJeeja KP struct hdac_bus *bus = ebus_to_hbus(ebus); 37d255b095SJeeja KP 38d255b095SJeeja KP if (!bus) 39d255b095SJeeja KP return -ENODEV; 40d255b095SJeeja KP 41d255b095SJeeja KP return bus->io_ops->dma_alloc_pages(bus, SNDRV_DMA_TYPE_DEV, size, dmab); 42d255b095SJeeja KP } 43d255b095SJeeja KP 44d255b095SJeeja KP static int skl_free_dma_buf(struct device *dev, struct snd_dma_buffer *dmab) 45d255b095SJeeja KP { 46d255b095SJeeja KP struct hdac_ext_bus *ebus = dev_get_drvdata(dev); 47d255b095SJeeja KP struct hdac_bus *bus = ebus_to_hbus(ebus); 48d255b095SJeeja KP 49d255b095SJeeja KP if (!bus) 50d255b095SJeeja KP return -ENODEV; 51d255b095SJeeja KP 52d255b095SJeeja KP bus->io_ops->dma_free_pages(bus, dmab); 53d255b095SJeeja KP 54d255b095SJeeja KP return 0; 55d255b095SJeeja KP } 56d255b095SJeeja KP 574e10996bSJeeja KP #define NOTIFICATION_PARAM_ID 3 584e10996bSJeeja KP #define NOTIFICATION_MASK 0xf 594e10996bSJeeja KP 604e10996bSJeeja KP /* disable notfication for underruns/overruns from firmware module */ 61cb729d80SG Kranthi void skl_dsp_enable_notification(struct skl_sst *ctx, bool enable) 624e10996bSJeeja KP { 634e10996bSJeeja KP struct notification_mask mask; 644e10996bSJeeja KP struct skl_ipc_large_config_msg msg = {0}; 654e10996bSJeeja KP 664e10996bSJeeja KP mask.notify = NOTIFICATION_MASK; 674e10996bSJeeja KP mask.enable = enable; 684e10996bSJeeja KP 694e10996bSJeeja KP msg.large_param_id = NOTIFICATION_PARAM_ID; 704e10996bSJeeja KP msg.param_data_size = sizeof(mask); 714e10996bSJeeja KP 724e10996bSJeeja KP skl_ipc_set_large_config(&ctx->ipc, &msg, (u32 *)&mask); 734e10996bSJeeja KP } 744e10996bSJeeja KP 7592eb4f62SJeeja KP static int skl_dsp_setup_spib(struct device *dev, unsigned int size, 7692eb4f62SJeeja KP int stream_tag, int enable) 7792eb4f62SJeeja KP { 7892eb4f62SJeeja KP struct hdac_ext_bus *ebus = dev_get_drvdata(dev); 7992eb4f62SJeeja KP struct hdac_bus *bus = ebus_to_hbus(ebus); 8092eb4f62SJeeja KP struct hdac_stream *stream = snd_hdac_get_stream(bus, 8192eb4f62SJeeja KP SNDRV_PCM_STREAM_PLAYBACK, stream_tag); 8292eb4f62SJeeja KP struct hdac_ext_stream *estream; 8392eb4f62SJeeja KP 8492eb4f62SJeeja KP if (!stream) 8592eb4f62SJeeja KP return -EINVAL; 8692eb4f62SJeeja KP 8792eb4f62SJeeja KP estream = stream_to_hdac_ext_stream(stream); 8892eb4f62SJeeja KP /* enable/disable SPIB for this hdac stream */ 8992eb4f62SJeeja KP snd_hdac_ext_stream_spbcap_enable(ebus, enable, stream->index); 9092eb4f62SJeeja KP 9192eb4f62SJeeja KP /* set the spib value */ 9292eb4f62SJeeja KP snd_hdac_ext_stream_set_spib(ebus, estream, size); 9392eb4f62SJeeja KP 9492eb4f62SJeeja KP return 0; 9592eb4f62SJeeja KP } 9692eb4f62SJeeja KP 9792eb4f62SJeeja KP static int skl_dsp_prepare(struct device *dev, unsigned int format, 9892eb4f62SJeeja KP unsigned int size, struct snd_dma_buffer *dmab) 9992eb4f62SJeeja KP { 10092eb4f62SJeeja KP struct hdac_ext_bus *ebus = dev_get_drvdata(dev); 10192eb4f62SJeeja KP struct hdac_bus *bus = ebus_to_hbus(ebus); 10292eb4f62SJeeja KP struct hdac_ext_stream *estream; 10392eb4f62SJeeja KP struct hdac_stream *stream; 10492eb4f62SJeeja KP struct snd_pcm_substream substream; 10592eb4f62SJeeja KP int ret; 10692eb4f62SJeeja KP 10792eb4f62SJeeja KP if (!bus) 10892eb4f62SJeeja KP return -ENODEV; 10992eb4f62SJeeja KP 11092eb4f62SJeeja KP memset(&substream, 0, sizeof(substream)); 11192eb4f62SJeeja KP substream.stream = SNDRV_PCM_STREAM_PLAYBACK; 11292eb4f62SJeeja KP 11392eb4f62SJeeja KP estream = snd_hdac_ext_stream_assign(ebus, &substream, 11492eb4f62SJeeja KP HDAC_EXT_STREAM_TYPE_HOST); 11592eb4f62SJeeja KP if (!estream) 11692eb4f62SJeeja KP return -ENODEV; 11792eb4f62SJeeja KP 11892eb4f62SJeeja KP stream = hdac_stream(estream); 11992eb4f62SJeeja KP 12092eb4f62SJeeja KP /* assign decouple host dma channel */ 12192eb4f62SJeeja KP ret = snd_hdac_dsp_prepare(stream, format, size, dmab); 12292eb4f62SJeeja KP if (ret < 0) 12392eb4f62SJeeja KP return ret; 12492eb4f62SJeeja KP 12592eb4f62SJeeja KP skl_dsp_setup_spib(dev, size, stream->stream_tag, true); 12692eb4f62SJeeja KP 12792eb4f62SJeeja KP return stream->stream_tag; 12892eb4f62SJeeja KP } 12992eb4f62SJeeja KP 13092eb4f62SJeeja KP static int skl_dsp_trigger(struct device *dev, bool start, int stream_tag) 13192eb4f62SJeeja KP { 13292eb4f62SJeeja KP struct hdac_ext_bus *ebus = dev_get_drvdata(dev); 13392eb4f62SJeeja KP struct hdac_stream *stream; 13492eb4f62SJeeja KP struct hdac_bus *bus = ebus_to_hbus(ebus); 13592eb4f62SJeeja KP 13692eb4f62SJeeja KP if (!bus) 13792eb4f62SJeeja KP return -ENODEV; 13892eb4f62SJeeja KP 13992eb4f62SJeeja KP stream = snd_hdac_get_stream(bus, 14092eb4f62SJeeja KP SNDRV_PCM_STREAM_PLAYBACK, stream_tag); 14192eb4f62SJeeja KP if (!stream) 14292eb4f62SJeeja KP return -EINVAL; 14392eb4f62SJeeja KP 14492eb4f62SJeeja KP snd_hdac_dsp_trigger(stream, start); 14592eb4f62SJeeja KP 14692eb4f62SJeeja KP return 0; 14792eb4f62SJeeja KP } 14892eb4f62SJeeja KP 14992eb4f62SJeeja KP static int skl_dsp_cleanup(struct device *dev, 15092eb4f62SJeeja KP struct snd_dma_buffer *dmab, int stream_tag) 15192eb4f62SJeeja KP { 15292eb4f62SJeeja KP struct hdac_ext_bus *ebus = dev_get_drvdata(dev); 15392eb4f62SJeeja KP struct hdac_stream *stream; 15492eb4f62SJeeja KP struct hdac_ext_stream *estream; 15592eb4f62SJeeja KP struct hdac_bus *bus = ebus_to_hbus(ebus); 15692eb4f62SJeeja KP 15792eb4f62SJeeja KP if (!bus) 15892eb4f62SJeeja KP return -ENODEV; 15992eb4f62SJeeja KP 16092eb4f62SJeeja KP stream = snd_hdac_get_stream(bus, 16192eb4f62SJeeja KP SNDRV_PCM_STREAM_PLAYBACK, stream_tag); 16292eb4f62SJeeja KP if (!stream) 16392eb4f62SJeeja KP return -EINVAL; 16492eb4f62SJeeja KP 16592eb4f62SJeeja KP estream = stream_to_hdac_ext_stream(stream); 16692eb4f62SJeeja KP skl_dsp_setup_spib(dev, 0, stream_tag, false); 16792eb4f62SJeeja KP snd_hdac_ext_stream_release(estream, HDAC_EXT_STREAM_TYPE_HOST); 16892eb4f62SJeeja KP 16992eb4f62SJeeja KP snd_hdac_dsp_cleanup(stream, dmab); 17092eb4f62SJeeja KP 17192eb4f62SJeeja KP return 0; 17292eb4f62SJeeja KP } 17392eb4f62SJeeja KP 174bc23ca35SJeeja KP static struct skl_dsp_loader_ops skl_get_loader_ops(void) 175bc23ca35SJeeja KP { 176bc23ca35SJeeja KP struct skl_dsp_loader_ops loader_ops; 177bc23ca35SJeeja KP 178bc23ca35SJeeja KP memset(&loader_ops, 0, sizeof(struct skl_dsp_loader_ops)); 179bc23ca35SJeeja KP 180bc23ca35SJeeja KP loader_ops.alloc_dma_buf = skl_alloc_dma_buf; 181bc23ca35SJeeja KP loader_ops.free_dma_buf = skl_free_dma_buf; 182bc23ca35SJeeja KP 183bc23ca35SJeeja KP return loader_ops; 184bc23ca35SJeeja KP }; 185bc23ca35SJeeja KP 18692eb4f62SJeeja KP static struct skl_dsp_loader_ops bxt_get_loader_ops(void) 18792eb4f62SJeeja KP { 18892eb4f62SJeeja KP struct skl_dsp_loader_ops loader_ops; 18992eb4f62SJeeja KP 19092eb4f62SJeeja KP memset(&loader_ops, 0, sizeof(loader_ops)); 19192eb4f62SJeeja KP 19292eb4f62SJeeja KP loader_ops.alloc_dma_buf = skl_alloc_dma_buf; 19392eb4f62SJeeja KP loader_ops.free_dma_buf = skl_free_dma_buf; 19492eb4f62SJeeja KP loader_ops.prepare = skl_dsp_prepare; 19592eb4f62SJeeja KP loader_ops.trigger = skl_dsp_trigger; 19692eb4f62SJeeja KP loader_ops.cleanup = skl_dsp_cleanup; 19792eb4f62SJeeja KP 19892eb4f62SJeeja KP return loader_ops; 19992eb4f62SJeeja KP }; 20092eb4f62SJeeja KP 201bc23ca35SJeeja KP static const struct skl_dsp_ops dsp_ops[] = { 202bc23ca35SJeeja KP { 203bc23ca35SJeeja KP .id = 0x9d70, 204bc23ca35SJeeja KP .loader_ops = skl_get_loader_ops, 205bc23ca35SJeeja KP .init = skl_sst_dsp_init, 20678cdbbdaSVinod Koul .init_fw = skl_sst_init_fw, 207bc23ca35SJeeja KP .cleanup = skl_sst_dsp_cleanup 208bc23ca35SJeeja KP }, 20992eb4f62SJeeja KP { 210451dfb5fSVinod Koul .id = 0x9d71, 211451dfb5fSVinod Koul .loader_ops = skl_get_loader_ops, 212451dfb5fSVinod Koul .init = skl_sst_dsp_init, 21378cdbbdaSVinod Koul .init_fw = skl_sst_init_fw, 214451dfb5fSVinod Koul .cleanup = skl_sst_dsp_cleanup 215451dfb5fSVinod Koul }, 216451dfb5fSVinod Koul { 21792eb4f62SJeeja KP .id = 0x5a98, 21892eb4f62SJeeja KP .loader_ops = bxt_get_loader_ops, 21992eb4f62SJeeja KP .init = bxt_sst_dsp_init, 22078cdbbdaSVinod Koul .init_fw = bxt_sst_init_fw, 22192eb4f62SJeeja KP .cleanup = bxt_sst_dsp_cleanup 22292eb4f62SJeeja KP }, 22325504863SVinod Koul { 22425504863SVinod Koul .id = 0x3198, 22525504863SVinod Koul .loader_ops = bxt_get_loader_ops, 22625504863SVinod Koul .init = bxt_sst_dsp_init, 22725504863SVinod Koul .init_fw = bxt_sst_init_fw, 22825504863SVinod Koul .cleanup = bxt_sst_dsp_cleanup 22925504863SVinod Koul }, 230bc23ca35SJeeja KP }; 231bc23ca35SJeeja KP 23273a67581SVinod Koul const struct skl_dsp_ops *skl_get_dsp_ops(int pci_id) 233bc23ca35SJeeja KP { 234bc23ca35SJeeja KP int i; 235bc23ca35SJeeja KP 236bc23ca35SJeeja KP for (i = 0; i < ARRAY_SIZE(dsp_ops); i++) { 237bc23ca35SJeeja KP if (dsp_ops[i].id == pci_id) 23873a67581SVinod Koul return &dsp_ops[i]; 239bc23ca35SJeeja KP } 240bc23ca35SJeeja KP 24173a67581SVinod Koul return NULL; 242bc23ca35SJeeja KP } 243bc23ca35SJeeja KP 244d255b095SJeeja KP int skl_init_dsp(struct skl *skl) 245d255b095SJeeja KP { 246d255b095SJeeja KP void __iomem *mmio_base; 247d255b095SJeeja KP struct hdac_ext_bus *ebus = &skl->ebus; 248d255b095SJeeja KP struct hdac_bus *bus = ebus_to_hbus(ebus); 249d255b095SJeeja KP struct skl_dsp_loader_ops loader_ops; 250bc23ca35SJeeja KP int irq = bus->irq; 25173a67581SVinod Koul const struct skl_dsp_ops *ops; 25273a67581SVinod Koul int ret; 253d255b095SJeeja KP 254d255b095SJeeja KP /* enable ppcap interrupt */ 255d255b095SJeeja KP snd_hdac_ext_bus_ppcap_enable(&skl->ebus, true); 256d255b095SJeeja KP snd_hdac_ext_bus_ppcap_int_enable(&skl->ebus, true); 257d255b095SJeeja KP 258d255b095SJeeja KP /* read the BAR of the ADSP MMIO */ 259d255b095SJeeja KP mmio_base = pci_ioremap_bar(skl->pci, 4); 260d255b095SJeeja KP if (mmio_base == NULL) { 261d255b095SJeeja KP dev_err(bus->dev, "ioremap error\n"); 262d255b095SJeeja KP return -ENXIO; 263d255b095SJeeja KP } 264d255b095SJeeja KP 26573a67581SVinod Koul ops = skl_get_dsp_ops(skl->pci->device); 26673a67581SVinod Koul if (!ops) 26773a67581SVinod Koul return -EIO; 268bc23ca35SJeeja KP 26973a67581SVinod Koul loader_ops = ops->loader_ops(); 27073a67581SVinod Koul ret = ops->init(bus->dev, mmio_base, irq, 27173a67581SVinod Koul skl->fw_name, loader_ops, 27273a67581SVinod Koul &skl->skl_sst); 273bc23ca35SJeeja KP 2742ac454ffSJeeja KP if (ret < 0) 2752ac454ffSJeeja KP return ret; 2762ac454ffSJeeja KP 2777bd86a30SG Kranthi skl->skl_sst->dsp_ops = ops; 278d255b095SJeeja KP dev_dbg(bus->dev, "dsp registration status=%d\n", ret); 279d255b095SJeeja KP 280d255b095SJeeja KP return ret; 281d255b095SJeeja KP } 282d255b095SJeeja KP 283bc23ca35SJeeja KP int skl_free_dsp(struct skl *skl) 284d255b095SJeeja KP { 285d255b095SJeeja KP struct hdac_ext_bus *ebus = &skl->ebus; 286d255b095SJeeja KP struct hdac_bus *bus = ebus_to_hbus(ebus); 287d255b095SJeeja KP struct skl_sst *ctx = skl->skl_sst; 288d255b095SJeeja KP 289d255b095SJeeja KP /* disable ppcap interrupt */ 290d255b095SJeeja KP snd_hdac_ext_bus_ppcap_int_enable(&skl->ebus, false); 291d255b095SJeeja KP 2927bd86a30SG Kranthi ctx->dsp_ops->cleanup(bus->dev, ctx); 293bc23ca35SJeeja KP 294d255b095SJeeja KP if (ctx->dsp->addr.lpe) 295d255b095SJeeja KP iounmap(ctx->dsp->addr.lpe); 296bc23ca35SJeeja KP 297bc23ca35SJeeja KP return 0; 298d255b095SJeeja KP } 299d255b095SJeeja KP 3008b4a133cSJayachandran B /* 3018b4a133cSJayachandran B * In the case of "suspend_active" i.e, the Audio IP being active 3028b4a133cSJayachandran B * during system suspend, immediately excecute any pending D0i3 work 3038b4a133cSJayachandran B * before suspending. This is needed for the IP to work in low power 3048b4a133cSJayachandran B * mode during system suspend. In the case of normal suspend, cancel 3058b4a133cSJayachandran B * any pending D0i3 work. 3068b4a133cSJayachandran B */ 3078b4a133cSJayachandran B int skl_suspend_late_dsp(struct skl *skl) 3088b4a133cSJayachandran B { 3098b4a133cSJayachandran B struct skl_sst *ctx = skl->skl_sst; 3108b4a133cSJayachandran B struct delayed_work *dwork; 3118b4a133cSJayachandran B 3128b4a133cSJayachandran B if (!ctx) 3138b4a133cSJayachandran B return 0; 3148b4a133cSJayachandran B 3158b4a133cSJayachandran B dwork = &ctx->d0i3.work; 3168b4a133cSJayachandran B 3178b4a133cSJayachandran B if (dwork->work.func) { 3188b4a133cSJayachandran B if (skl->supend_active) 3198b4a133cSJayachandran B flush_delayed_work(dwork); 3208b4a133cSJayachandran B else 3218b4a133cSJayachandran B cancel_delayed_work_sync(dwork); 3228b4a133cSJayachandran B } 3238b4a133cSJayachandran B 3248b4a133cSJayachandran B return 0; 3258b4a133cSJayachandran B } 3268b4a133cSJayachandran B 327d255b095SJeeja KP int skl_suspend_dsp(struct skl *skl) 328d255b095SJeeja KP { 329d255b095SJeeja KP struct skl_sst *ctx = skl->skl_sst; 330d255b095SJeeja KP int ret; 331d255b095SJeeja KP 332d255b095SJeeja KP /* if ppcap is not supported return 0 */ 333ec8ae570SVinod Koul if (!skl->ebus.bus.ppcap) 334d255b095SJeeja KP return 0; 335d255b095SJeeja KP 336d255b095SJeeja KP ret = skl_dsp_sleep(ctx->dsp); 337d255b095SJeeja KP if (ret < 0) 338d255b095SJeeja KP return ret; 339d255b095SJeeja KP 340d255b095SJeeja KP /* disable ppcap interrupt */ 341d255b095SJeeja KP snd_hdac_ext_bus_ppcap_int_enable(&skl->ebus, false); 342d255b095SJeeja KP snd_hdac_ext_bus_ppcap_enable(&skl->ebus, false); 343d255b095SJeeja KP 344d255b095SJeeja KP return 0; 345d255b095SJeeja KP } 346d255b095SJeeja KP 347d255b095SJeeja KP int skl_resume_dsp(struct skl *skl) 348d255b095SJeeja KP { 349d255b095SJeeja KP struct skl_sst *ctx = skl->skl_sst; 3504e10996bSJeeja KP int ret; 351d255b095SJeeja KP 352d255b095SJeeja KP /* if ppcap is not supported return 0 */ 353ec8ae570SVinod Koul if (!skl->ebus.bus.ppcap) 354d255b095SJeeja KP return 0; 355d255b095SJeeja KP 356d255b095SJeeja KP /* enable ppcap interrupt */ 357d255b095SJeeja KP snd_hdac_ext_bus_ppcap_enable(&skl->ebus, true); 358d255b095SJeeja KP snd_hdac_ext_bus_ppcap_int_enable(&skl->ebus, true); 359d255b095SJeeja KP 36078cdbbdaSVinod Koul /* check if DSP 1st boot is done */ 36178cdbbdaSVinod Koul if (skl->skl_sst->is_first_boot == true) 36278cdbbdaSVinod Koul return 0; 36378cdbbdaSVinod Koul 3644e10996bSJeeja KP ret = skl_dsp_wake(ctx->dsp); 3654e10996bSJeeja KP if (ret < 0) 3664e10996bSJeeja KP return ret; 3674e10996bSJeeja KP 3684e10996bSJeeja KP skl_dsp_enable_notification(skl->skl_sst, false); 3694e10996bSJeeja KP return ret; 370d255b095SJeeja KP } 37123db472bSJeeja KP 37223db472bSJeeja KP enum skl_bitdepth skl_get_bit_depth(int params) 37323db472bSJeeja KP { 37423db472bSJeeja KP switch (params) { 37523db472bSJeeja KP case 8: 37623db472bSJeeja KP return SKL_DEPTH_8BIT; 37723db472bSJeeja KP 37823db472bSJeeja KP case 16: 37923db472bSJeeja KP return SKL_DEPTH_16BIT; 38023db472bSJeeja KP 38123db472bSJeeja KP case 24: 38223db472bSJeeja KP return SKL_DEPTH_24BIT; 38323db472bSJeeja KP 38423db472bSJeeja KP case 32: 38523db472bSJeeja KP return SKL_DEPTH_32BIT; 38623db472bSJeeja KP 38723db472bSJeeja KP default: 38823db472bSJeeja KP return SKL_DEPTH_INVALID; 38923db472bSJeeja KP 39023db472bSJeeja KP } 39123db472bSJeeja KP } 39223db472bSJeeja KP 39323db472bSJeeja KP /* 39423db472bSJeeja KP * Each module in DSP expects a base module configuration, which consists of 39523db472bSJeeja KP * PCM format information, which we calculate in driver and resource values 39623db472bSJeeja KP * which are read from widget information passed through topology binary 39723db472bSJeeja KP * This is send when we create a module with INIT_INSTANCE IPC msg 39823db472bSJeeja KP */ 39923db472bSJeeja KP static void skl_set_base_module_format(struct skl_sst *ctx, 40023db472bSJeeja KP struct skl_module_cfg *mconfig, 40123db472bSJeeja KP struct skl_base_cfg *base_cfg) 40223db472bSJeeja KP { 4034cd9899fSHardik T Shah struct skl_module_fmt *format = &mconfig->in_fmt[0]; 40423db472bSJeeja KP 40523db472bSJeeja KP base_cfg->audio_fmt.number_of_channels = (u8)format->channels; 40623db472bSJeeja KP 40723db472bSJeeja KP base_cfg->audio_fmt.s_freq = format->s_freq; 40823db472bSJeeja KP base_cfg->audio_fmt.bit_depth = format->bit_depth; 40923db472bSJeeja KP base_cfg->audio_fmt.valid_bit_depth = format->valid_bit_depth; 41023db472bSJeeja KP base_cfg->audio_fmt.ch_cfg = format->ch_cfg; 41123db472bSJeeja KP 41223db472bSJeeja KP dev_dbg(ctx->dev, "bit_depth=%x valid_bd=%x ch_config=%x\n", 41323db472bSJeeja KP format->bit_depth, format->valid_bit_depth, 41423db472bSJeeja KP format->ch_cfg); 41523db472bSJeeja KP 4163e81f1a3SJeeja KP base_cfg->audio_fmt.channel_map = format->ch_map; 41723db472bSJeeja KP 4183e81f1a3SJeeja KP base_cfg->audio_fmt.interleaving = format->interleaving_style; 41923db472bSJeeja KP 42023db472bSJeeja KP base_cfg->cps = mconfig->mcps; 42123db472bSJeeja KP base_cfg->ibs = mconfig->ibs; 42223db472bSJeeja KP base_cfg->obs = mconfig->obs; 423b18c458dSJeeja KP base_cfg->is_pages = mconfig->mem_pages; 42423db472bSJeeja KP } 42523db472bSJeeja KP 42623db472bSJeeja KP /* 42723db472bSJeeja KP * Copies copier capabilities into copier module and updates copier module 42823db472bSJeeja KP * config size. 42923db472bSJeeja KP */ 43023db472bSJeeja KP static void skl_copy_copier_caps(struct skl_module_cfg *mconfig, 43123db472bSJeeja KP struct skl_cpr_cfg *cpr_mconfig) 43223db472bSJeeja KP { 43323db472bSJeeja KP if (mconfig->formats_config.caps_size == 0) 43423db472bSJeeja KP return; 43523db472bSJeeja KP 43623db472bSJeeja KP memcpy(cpr_mconfig->gtw_cfg.config_data, 43723db472bSJeeja KP mconfig->formats_config.caps, 43823db472bSJeeja KP mconfig->formats_config.caps_size); 43923db472bSJeeja KP 44023db472bSJeeja KP cpr_mconfig->gtw_cfg.config_length = 44123db472bSJeeja KP (mconfig->formats_config.caps_size) / 4; 44223db472bSJeeja KP } 44323db472bSJeeja KP 444bfa764acSJeeja KP #define SKL_NON_GATEWAY_CPR_NODE_ID 0xFFFFFFFF 44523db472bSJeeja KP /* 44623db472bSJeeja KP * Calculate the gatewat settings required for copier module, type of 44723db472bSJeeja KP * gateway and index of gateway to use 44823db472bSJeeja KP */ 4494fdf810fSDharageswari.R static u32 skl_get_node_id(struct skl_sst *ctx, 4504fdf810fSDharageswari.R struct skl_module_cfg *mconfig) 45123db472bSJeeja KP { 45223db472bSJeeja KP union skl_connector_node_id node_id = {0}; 453d7b18813SJeeja KP union skl_ssp_dma_node ssp_node = {0}; 45423db472bSJeeja KP struct skl_pipe_params *params = mconfig->pipe->p_params; 45523db472bSJeeja KP 45623db472bSJeeja KP switch (mconfig->dev_type) { 45723db472bSJeeja KP case SKL_DEVICE_BT: 45823db472bSJeeja KP node_id.node.dma_type = 45923db472bSJeeja KP (SKL_CONN_SOURCE == mconfig->hw_conn_type) ? 46023db472bSJeeja KP SKL_DMA_I2S_LINK_OUTPUT_CLASS : 46123db472bSJeeja KP SKL_DMA_I2S_LINK_INPUT_CLASS; 46223db472bSJeeja KP node_id.node.vindex = params->host_dma_id + 46323db472bSJeeja KP (mconfig->vbus_id << 3); 46423db472bSJeeja KP break; 46523db472bSJeeja KP 46623db472bSJeeja KP case SKL_DEVICE_I2S: 46723db472bSJeeja KP node_id.node.dma_type = 46823db472bSJeeja KP (SKL_CONN_SOURCE == mconfig->hw_conn_type) ? 46923db472bSJeeja KP SKL_DMA_I2S_LINK_OUTPUT_CLASS : 47023db472bSJeeja KP SKL_DMA_I2S_LINK_INPUT_CLASS; 471d7b18813SJeeja KP ssp_node.dma_node.time_slot_index = mconfig->time_slot; 472d7b18813SJeeja KP ssp_node.dma_node.i2s_instance = mconfig->vbus_id; 473d7b18813SJeeja KP node_id.node.vindex = ssp_node.val; 47423db472bSJeeja KP break; 47523db472bSJeeja KP 47623db472bSJeeja KP case SKL_DEVICE_DMIC: 47723db472bSJeeja KP node_id.node.dma_type = SKL_DMA_DMIC_LINK_INPUT_CLASS; 47823db472bSJeeja KP node_id.node.vindex = mconfig->vbus_id + 47923db472bSJeeja KP (mconfig->time_slot); 48023db472bSJeeja KP break; 48123db472bSJeeja KP 48223db472bSJeeja KP case SKL_DEVICE_HDALINK: 48323db472bSJeeja KP node_id.node.dma_type = 48423db472bSJeeja KP (SKL_CONN_SOURCE == mconfig->hw_conn_type) ? 48523db472bSJeeja KP SKL_DMA_HDA_LINK_OUTPUT_CLASS : 48623db472bSJeeja KP SKL_DMA_HDA_LINK_INPUT_CLASS; 48723db472bSJeeja KP node_id.node.vindex = params->link_dma_id; 48823db472bSJeeja KP break; 48923db472bSJeeja KP 490bfa764acSJeeja KP case SKL_DEVICE_HDAHOST: 49123db472bSJeeja KP node_id.node.dma_type = 49223db472bSJeeja KP (SKL_CONN_SOURCE == mconfig->hw_conn_type) ? 49323db472bSJeeja KP SKL_DMA_HDA_HOST_OUTPUT_CLASS : 49423db472bSJeeja KP SKL_DMA_HDA_HOST_INPUT_CLASS; 49523db472bSJeeja KP node_id.node.vindex = params->host_dma_id; 49623db472bSJeeja KP break; 497bfa764acSJeeja KP 498bfa764acSJeeja KP default: 4994fdf810fSDharageswari.R node_id.val = 0xFFFFFFFF; 5004fdf810fSDharageswari.R break; 5014fdf810fSDharageswari.R } 5024fdf810fSDharageswari.R 5034fdf810fSDharageswari.R return node_id.val; 5044fdf810fSDharageswari.R } 5054fdf810fSDharageswari.R 5064fdf810fSDharageswari.R static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx, 5074fdf810fSDharageswari.R struct skl_module_cfg *mconfig, 5084fdf810fSDharageswari.R struct skl_cpr_cfg *cpr_mconfig) 5094fdf810fSDharageswari.R { 5104fdf810fSDharageswari.R cpr_mconfig->gtw_cfg.node_id = skl_get_node_id(ctx, mconfig); 5114fdf810fSDharageswari.R 5124fdf810fSDharageswari.R if (cpr_mconfig->gtw_cfg.node_id == SKL_NON_GATEWAY_CPR_NODE_ID) { 513bfa764acSJeeja KP cpr_mconfig->cpr_feature_mask = 0; 514bfa764acSJeeja KP return; 51523db472bSJeeja KP } 51623db472bSJeeja KP 51723db472bSJeeja KP if (SKL_CONN_SOURCE == mconfig->hw_conn_type) 51823db472bSJeeja KP cpr_mconfig->gtw_cfg.dma_buffer_size = 2 * mconfig->obs; 51923db472bSJeeja KP else 52023db472bSJeeja KP cpr_mconfig->gtw_cfg.dma_buffer_size = 2 * mconfig->ibs; 52123db472bSJeeja KP 52223db472bSJeeja KP cpr_mconfig->cpr_feature_mask = 0; 52323db472bSJeeja KP cpr_mconfig->gtw_cfg.config_length = 0; 52423db472bSJeeja KP 52523db472bSJeeja KP skl_copy_copier_caps(mconfig, cpr_mconfig); 52623db472bSJeeja KP } 52723db472bSJeeja KP 528c115fa5eSDharageswari.R #define DMA_CONTROL_ID 5 529c115fa5eSDharageswari.R 530c115fa5eSDharageswari.R int skl_dsp_set_dma_control(struct skl_sst *ctx, struct skl_module_cfg *mconfig) 531c115fa5eSDharageswari.R { 532c115fa5eSDharageswari.R struct skl_dma_control *dma_ctrl; 533c115fa5eSDharageswari.R struct skl_ipc_large_config_msg msg = {0}; 534c115fa5eSDharageswari.R int err = 0; 535c115fa5eSDharageswari.R 536c115fa5eSDharageswari.R 537c115fa5eSDharageswari.R /* 538c186fe74SGuruprasadX Pawse * if blob size zero, then return 539c115fa5eSDharageswari.R */ 540c186fe74SGuruprasadX Pawse if (mconfig->formats_config.caps_size == 0) 541c115fa5eSDharageswari.R return 0; 542c115fa5eSDharageswari.R 543c115fa5eSDharageswari.R msg.large_param_id = DMA_CONTROL_ID; 544c115fa5eSDharageswari.R msg.param_data_size = sizeof(struct skl_dma_control) + 545c115fa5eSDharageswari.R mconfig->formats_config.caps_size; 546c115fa5eSDharageswari.R 547c115fa5eSDharageswari.R dma_ctrl = kzalloc(msg.param_data_size, GFP_KERNEL); 548c115fa5eSDharageswari.R if (dma_ctrl == NULL) 549c115fa5eSDharageswari.R return -ENOMEM; 550c115fa5eSDharageswari.R 551c115fa5eSDharageswari.R dma_ctrl->node_id = skl_get_node_id(ctx, mconfig); 552c115fa5eSDharageswari.R 553c115fa5eSDharageswari.R /* size in dwords */ 554c186fe74SGuruprasadX Pawse dma_ctrl->config_length = mconfig->formats_config.caps_size / 4; 555c115fa5eSDharageswari.R 556c115fa5eSDharageswari.R memcpy(dma_ctrl->config_data, mconfig->formats_config.caps, 557c115fa5eSDharageswari.R mconfig->formats_config.caps_size); 558c115fa5eSDharageswari.R 559c115fa5eSDharageswari.R err = skl_ipc_set_large_config(&ctx->ipc, &msg, (u32 *)dma_ctrl); 560c115fa5eSDharageswari.R 561c115fa5eSDharageswari.R kfree(dma_ctrl); 562c115fa5eSDharageswari.R return err; 563c115fa5eSDharageswari.R } 564c115fa5eSDharageswari.R 56523db472bSJeeja KP static void skl_setup_out_format(struct skl_sst *ctx, 56623db472bSJeeja KP struct skl_module_cfg *mconfig, 56723db472bSJeeja KP struct skl_audio_data_format *out_fmt) 56823db472bSJeeja KP { 5694cd9899fSHardik T Shah struct skl_module_fmt *format = &mconfig->out_fmt[0]; 57023db472bSJeeja KP 57123db472bSJeeja KP out_fmt->number_of_channels = (u8)format->channels; 57223db472bSJeeja KP out_fmt->s_freq = format->s_freq; 57323db472bSJeeja KP out_fmt->bit_depth = format->bit_depth; 57423db472bSJeeja KP out_fmt->valid_bit_depth = format->valid_bit_depth; 57523db472bSJeeja KP out_fmt->ch_cfg = format->ch_cfg; 57623db472bSJeeja KP 5773e81f1a3SJeeja KP out_fmt->channel_map = format->ch_map; 5783e81f1a3SJeeja KP out_fmt->interleaving = format->interleaving_style; 5793e81f1a3SJeeja KP out_fmt->sample_type = format->sample_type; 58023db472bSJeeja KP 58123db472bSJeeja KP dev_dbg(ctx->dev, "copier out format chan=%d fre=%d bitdepth=%d\n", 58223db472bSJeeja KP out_fmt->number_of_channels, format->s_freq, format->bit_depth); 58323db472bSJeeja KP } 58423db472bSJeeja KP 58523db472bSJeeja KP /* 586a0ffe48bSHardik T Shah * DSP needs SRC module for frequency conversion, SRC takes base module 587a0ffe48bSHardik T Shah * configuration and the target frequency as extra parameter passed as src 588a0ffe48bSHardik T Shah * config 589a0ffe48bSHardik T Shah */ 590a0ffe48bSHardik T Shah static void skl_set_src_format(struct skl_sst *ctx, 591a0ffe48bSHardik T Shah struct skl_module_cfg *mconfig, 592a0ffe48bSHardik T Shah struct skl_src_module_cfg *src_mconfig) 593a0ffe48bSHardik T Shah { 5944cd9899fSHardik T Shah struct skl_module_fmt *fmt = &mconfig->out_fmt[0]; 595a0ffe48bSHardik T Shah 596a0ffe48bSHardik T Shah skl_set_base_module_format(ctx, mconfig, 597a0ffe48bSHardik T Shah (struct skl_base_cfg *)src_mconfig); 598a0ffe48bSHardik T Shah 599a0ffe48bSHardik T Shah src_mconfig->src_cfg = fmt->s_freq; 600a0ffe48bSHardik T Shah } 601a0ffe48bSHardik T Shah 602a0ffe48bSHardik T Shah /* 603a0ffe48bSHardik T Shah * DSP needs updown module to do channel conversion. updown module take base 604a0ffe48bSHardik T Shah * module configuration and channel configuration 605a0ffe48bSHardik T Shah * It also take coefficients and now we have defaults applied here 606a0ffe48bSHardik T Shah */ 607a0ffe48bSHardik T Shah static void skl_set_updown_mixer_format(struct skl_sst *ctx, 608a0ffe48bSHardik T Shah struct skl_module_cfg *mconfig, 609a0ffe48bSHardik T Shah struct skl_up_down_mixer_cfg *mixer_mconfig) 610a0ffe48bSHardik T Shah { 6114cd9899fSHardik T Shah struct skl_module_fmt *fmt = &mconfig->out_fmt[0]; 612a0ffe48bSHardik T Shah int i = 0; 613a0ffe48bSHardik T Shah 614a0ffe48bSHardik T Shah skl_set_base_module_format(ctx, mconfig, 615a0ffe48bSHardik T Shah (struct skl_base_cfg *)mixer_mconfig); 616a0ffe48bSHardik T Shah mixer_mconfig->out_ch_cfg = fmt->ch_cfg; 617a0ffe48bSHardik T Shah 618a0ffe48bSHardik T Shah /* Select F/W default coefficient */ 619a0ffe48bSHardik T Shah mixer_mconfig->coeff_sel = 0x0; 620a0ffe48bSHardik T Shah 621a0ffe48bSHardik T Shah /* User coeff, don't care since we are selecting F/W defaults */ 622a0ffe48bSHardik T Shah for (i = 0; i < UP_DOWN_MIXER_MAX_COEFF; i++) 623a0ffe48bSHardik T Shah mixer_mconfig->coeff[i] = 0xDEADBEEF; 624a0ffe48bSHardik T Shah } 625a0ffe48bSHardik T Shah 626a0ffe48bSHardik T Shah /* 62723db472bSJeeja KP * 'copier' is DSP internal module which copies data from Host DMA (HDA host 62823db472bSJeeja KP * dma) or link (hda link, SSP, PDM) 62923db472bSJeeja KP * Here we calculate the copier module parameters, like PCM format, output 63023db472bSJeeja KP * format, gateway settings 63123db472bSJeeja KP * copier_module_config is sent as input buffer with INIT_INSTANCE IPC msg 63223db472bSJeeja KP */ 63323db472bSJeeja KP static void skl_set_copier_format(struct skl_sst *ctx, 63423db472bSJeeja KP struct skl_module_cfg *mconfig, 63523db472bSJeeja KP struct skl_cpr_cfg *cpr_mconfig) 63623db472bSJeeja KP { 63723db472bSJeeja KP struct skl_audio_data_format *out_fmt = &cpr_mconfig->out_fmt; 63823db472bSJeeja KP struct skl_base_cfg *base_cfg = (struct skl_base_cfg *)cpr_mconfig; 63923db472bSJeeja KP 64023db472bSJeeja KP skl_set_base_module_format(ctx, mconfig, base_cfg); 64123db472bSJeeja KP 64223db472bSJeeja KP skl_setup_out_format(ctx, mconfig, out_fmt); 64323db472bSJeeja KP skl_setup_cpr_gateway_cfg(ctx, mconfig, cpr_mconfig); 64423db472bSJeeja KP } 64523db472bSJeeja KP 646399b210bSJeeja KP /* 647399b210bSJeeja KP * Algo module are DSP pre processing modules. Algo module take base module 648399b210bSJeeja KP * configuration and params 649399b210bSJeeja KP */ 650399b210bSJeeja KP 651399b210bSJeeja KP static void skl_set_algo_format(struct skl_sst *ctx, 652399b210bSJeeja KP struct skl_module_cfg *mconfig, 653399b210bSJeeja KP struct skl_algo_cfg *algo_mcfg) 654399b210bSJeeja KP { 655399b210bSJeeja KP struct skl_base_cfg *base_cfg = (struct skl_base_cfg *)algo_mcfg; 656399b210bSJeeja KP 657399b210bSJeeja KP skl_set_base_module_format(ctx, mconfig, base_cfg); 658399b210bSJeeja KP 659399b210bSJeeja KP if (mconfig->formats_config.caps_size == 0) 660399b210bSJeeja KP return; 661399b210bSJeeja KP 662399b210bSJeeja KP memcpy(algo_mcfg->params, 663399b210bSJeeja KP mconfig->formats_config.caps, 664399b210bSJeeja KP mconfig->formats_config.caps_size); 665399b210bSJeeja KP 666399b210bSJeeja KP } 667399b210bSJeeja KP 668fd18110fSDharageswari R /* 669fd18110fSDharageswari R * Mic select module allows selecting one or many input channels, thus 670fd18110fSDharageswari R * acting as a demux. 671fd18110fSDharageswari R * 672fd18110fSDharageswari R * Mic select module take base module configuration and out-format 673fd18110fSDharageswari R * configuration 674fd18110fSDharageswari R */ 675fd18110fSDharageswari R static void skl_set_base_outfmt_format(struct skl_sst *ctx, 676fd18110fSDharageswari R struct skl_module_cfg *mconfig, 677fd18110fSDharageswari R struct skl_base_outfmt_cfg *base_outfmt_mcfg) 678fd18110fSDharageswari R { 679fd18110fSDharageswari R struct skl_audio_data_format *out_fmt = &base_outfmt_mcfg->out_fmt; 680fd18110fSDharageswari R struct skl_base_cfg *base_cfg = 681fd18110fSDharageswari R (struct skl_base_cfg *)base_outfmt_mcfg; 682fd18110fSDharageswari R 683fd18110fSDharageswari R skl_set_base_module_format(ctx, mconfig, base_cfg); 684fd18110fSDharageswari R skl_setup_out_format(ctx, mconfig, out_fmt); 685fd18110fSDharageswari R } 686fd18110fSDharageswari R 68723db472bSJeeja KP static u16 skl_get_module_param_size(struct skl_sst *ctx, 68823db472bSJeeja KP struct skl_module_cfg *mconfig) 68923db472bSJeeja KP { 69023db472bSJeeja KP u16 param_size; 69123db472bSJeeja KP 69223db472bSJeeja KP switch (mconfig->m_type) { 69323db472bSJeeja KP case SKL_MODULE_TYPE_COPIER: 69423db472bSJeeja KP param_size = sizeof(struct skl_cpr_cfg); 69523db472bSJeeja KP param_size += mconfig->formats_config.caps_size; 69623db472bSJeeja KP return param_size; 69723db472bSJeeja KP 698a0ffe48bSHardik T Shah case SKL_MODULE_TYPE_SRCINT: 699a0ffe48bSHardik T Shah return sizeof(struct skl_src_module_cfg); 700a0ffe48bSHardik T Shah 701a0ffe48bSHardik T Shah case SKL_MODULE_TYPE_UPDWMIX: 702a0ffe48bSHardik T Shah return sizeof(struct skl_up_down_mixer_cfg); 703a0ffe48bSHardik T Shah 704399b210bSJeeja KP case SKL_MODULE_TYPE_ALGO: 705399b210bSJeeja KP param_size = sizeof(struct skl_base_cfg); 706399b210bSJeeja KP param_size += mconfig->formats_config.caps_size; 707399b210bSJeeja KP return param_size; 708399b210bSJeeja KP 709fd18110fSDharageswari R case SKL_MODULE_TYPE_BASE_OUTFMT: 7105e8f0ee4SDharageswari R case SKL_MODULE_TYPE_KPB: 711fd18110fSDharageswari R return sizeof(struct skl_base_outfmt_cfg); 712fd18110fSDharageswari R 71323db472bSJeeja KP default: 71423db472bSJeeja KP /* 71523db472bSJeeja KP * return only base cfg when no specific module type is 71623db472bSJeeja KP * specified 71723db472bSJeeja KP */ 71823db472bSJeeja KP return sizeof(struct skl_base_cfg); 71923db472bSJeeja KP } 72023db472bSJeeja KP 72123db472bSJeeja KP return 0; 72223db472bSJeeja KP } 72323db472bSJeeja KP 72423db472bSJeeja KP /* 725a0ffe48bSHardik T Shah * DSP firmware supports various modules like copier, SRC, updown etc. 726a0ffe48bSHardik T Shah * These modules required various parameters to be calculated and sent for 727a0ffe48bSHardik T Shah * the module initialization to DSP. By default a generic module needs only 728a0ffe48bSHardik T Shah * base module format configuration 72923db472bSJeeja KP */ 730a0ffe48bSHardik T Shah 73123db472bSJeeja KP static int skl_set_module_format(struct skl_sst *ctx, 73223db472bSJeeja KP struct skl_module_cfg *module_config, 73323db472bSJeeja KP u16 *module_config_size, 73423db472bSJeeja KP void **param_data) 73523db472bSJeeja KP { 73623db472bSJeeja KP u16 param_size; 73723db472bSJeeja KP 73823db472bSJeeja KP param_size = skl_get_module_param_size(ctx, module_config); 73923db472bSJeeja KP 74023db472bSJeeja KP *param_data = kzalloc(param_size, GFP_KERNEL); 74123db472bSJeeja KP if (NULL == *param_data) 74223db472bSJeeja KP return -ENOMEM; 74323db472bSJeeja KP 74423db472bSJeeja KP *module_config_size = param_size; 74523db472bSJeeja KP 74623db472bSJeeja KP switch (module_config->m_type) { 74723db472bSJeeja KP case SKL_MODULE_TYPE_COPIER: 74823db472bSJeeja KP skl_set_copier_format(ctx, module_config, *param_data); 74923db472bSJeeja KP break; 75023db472bSJeeja KP 751a0ffe48bSHardik T Shah case SKL_MODULE_TYPE_SRCINT: 752a0ffe48bSHardik T Shah skl_set_src_format(ctx, module_config, *param_data); 753a0ffe48bSHardik T Shah break; 754a0ffe48bSHardik T Shah 755a0ffe48bSHardik T Shah case SKL_MODULE_TYPE_UPDWMIX: 756a0ffe48bSHardik T Shah skl_set_updown_mixer_format(ctx, module_config, *param_data); 757a0ffe48bSHardik T Shah break; 758a0ffe48bSHardik T Shah 759399b210bSJeeja KP case SKL_MODULE_TYPE_ALGO: 760399b210bSJeeja KP skl_set_algo_format(ctx, module_config, *param_data); 761399b210bSJeeja KP break; 762399b210bSJeeja KP 763fd18110fSDharageswari R case SKL_MODULE_TYPE_BASE_OUTFMT: 7645e8f0ee4SDharageswari R case SKL_MODULE_TYPE_KPB: 765fd18110fSDharageswari R skl_set_base_outfmt_format(ctx, module_config, *param_data); 766fd18110fSDharageswari R break; 767fd18110fSDharageswari R 76823db472bSJeeja KP default: 76923db472bSJeeja KP skl_set_base_module_format(ctx, module_config, *param_data); 77023db472bSJeeja KP break; 77123db472bSJeeja KP 77223db472bSJeeja KP } 77323db472bSJeeja KP 77423db472bSJeeja KP dev_dbg(ctx->dev, "Module type=%d config size: %d bytes\n", 77523db472bSJeeja KP module_config->id.module_id, param_size); 77691c18325SVedang Patel print_hex_dump_debug("Module params:", DUMP_PREFIX_OFFSET, 8, 4, 77723db472bSJeeja KP *param_data, param_size, false); 77823db472bSJeeja KP return 0; 77923db472bSJeeja KP } 78023db472bSJeeja KP 78123db472bSJeeja KP static int skl_get_queue_index(struct skl_module_pin *mpin, 78223db472bSJeeja KP struct skl_module_inst_id id, int max) 78323db472bSJeeja KP { 78423db472bSJeeja KP int i; 78523db472bSJeeja KP 78623db472bSJeeja KP for (i = 0; i < max; i++) { 78723db472bSJeeja KP if (mpin[i].id.module_id == id.module_id && 78823db472bSJeeja KP mpin[i].id.instance_id == id.instance_id) 78923db472bSJeeja KP return i; 79023db472bSJeeja KP } 79123db472bSJeeja KP 79223db472bSJeeja KP return -EINVAL; 79323db472bSJeeja KP } 79423db472bSJeeja KP 79523db472bSJeeja KP /* 79623db472bSJeeja KP * Allocates queue for each module. 79723db472bSJeeja KP * if dynamic, the pin_index is allocated 0 to max_pin. 79823db472bSJeeja KP * In static, the pin_index is fixed based on module_id and instance id 79923db472bSJeeja KP */ 80023db472bSJeeja KP static int skl_alloc_queue(struct skl_module_pin *mpin, 8014f745708SJeeja KP struct skl_module_cfg *tgt_cfg, int max) 80223db472bSJeeja KP { 80323db472bSJeeja KP int i; 8044f745708SJeeja KP struct skl_module_inst_id id = tgt_cfg->id; 80523db472bSJeeja KP /* 80623db472bSJeeja KP * if pin in dynamic, find first free pin 80723db472bSJeeja KP * otherwise find match module and instance id pin as topology will 80823db472bSJeeja KP * ensure a unique pin is assigned to this so no need to 80923db472bSJeeja KP * allocate/free 81023db472bSJeeja KP */ 81123db472bSJeeja KP for (i = 0; i < max; i++) { 81223db472bSJeeja KP if (mpin[i].is_dynamic) { 8134f745708SJeeja KP if (!mpin[i].in_use && 8144f745708SJeeja KP mpin[i].pin_state == SKL_PIN_UNBIND) { 8154f745708SJeeja KP 81623db472bSJeeja KP mpin[i].in_use = true; 81723db472bSJeeja KP mpin[i].id.module_id = id.module_id; 81823db472bSJeeja KP mpin[i].id.instance_id = id.instance_id; 819ef2a352cSDharageswari R mpin[i].id.pvt_id = id.pvt_id; 8204f745708SJeeja KP mpin[i].tgt_mcfg = tgt_cfg; 82123db472bSJeeja KP return i; 82223db472bSJeeja KP } 82323db472bSJeeja KP } else { 82423db472bSJeeja KP if (mpin[i].id.module_id == id.module_id && 8254f745708SJeeja KP mpin[i].id.instance_id == id.instance_id && 8264f745708SJeeja KP mpin[i].pin_state == SKL_PIN_UNBIND) { 8274f745708SJeeja KP 8284f745708SJeeja KP mpin[i].tgt_mcfg = tgt_cfg; 82923db472bSJeeja KP return i; 83023db472bSJeeja KP } 83123db472bSJeeja KP } 8324f745708SJeeja KP } 83323db472bSJeeja KP 83423db472bSJeeja KP return -EINVAL; 83523db472bSJeeja KP } 83623db472bSJeeja KP 83723db472bSJeeja KP static void skl_free_queue(struct skl_module_pin *mpin, int q_index) 83823db472bSJeeja KP { 83923db472bSJeeja KP if (mpin[q_index].is_dynamic) { 84023db472bSJeeja KP mpin[q_index].in_use = false; 84123db472bSJeeja KP mpin[q_index].id.module_id = 0; 84223db472bSJeeja KP mpin[q_index].id.instance_id = 0; 843ef2a352cSDharageswari R mpin[q_index].id.pvt_id = 0; 84423db472bSJeeja KP } 8454f745708SJeeja KP mpin[q_index].pin_state = SKL_PIN_UNBIND; 8464f745708SJeeja KP mpin[q_index].tgt_mcfg = NULL; 8474f745708SJeeja KP } 8484f745708SJeeja KP 8494f745708SJeeja KP /* Module state will be set to unint, if all the out pin state is UNBIND */ 8504f745708SJeeja KP 8514f745708SJeeja KP static void skl_clear_module_state(struct skl_module_pin *mpin, int max, 8524f745708SJeeja KP struct skl_module_cfg *mcfg) 8534f745708SJeeja KP { 8544f745708SJeeja KP int i; 8554f745708SJeeja KP bool found = false; 8564f745708SJeeja KP 8574f745708SJeeja KP for (i = 0; i < max; i++) { 8584f745708SJeeja KP if (mpin[i].pin_state == SKL_PIN_UNBIND) 8594f745708SJeeja KP continue; 8604f745708SJeeja KP found = true; 8614f745708SJeeja KP break; 8624f745708SJeeja KP } 8634f745708SJeeja KP 8644f745708SJeeja KP if (!found) 865473a4d51SJeeja KP mcfg->m_state = SKL_MODULE_INIT_DONE; 8664f745708SJeeja KP return; 86723db472bSJeeja KP } 868beb73b26SJeeja KP 869beb73b26SJeeja KP /* 870beb73b26SJeeja KP * A module needs to be instanataited in DSP. A mdoule is present in a 871beb73b26SJeeja KP * collection of module referred as a PIPE. 872beb73b26SJeeja KP * We first calculate the module format, based on module type and then 873beb73b26SJeeja KP * invoke the DSP by sending IPC INIT_INSTANCE using ipc helper 874beb73b26SJeeja KP */ 875beb73b26SJeeja KP int skl_init_module(struct skl_sst *ctx, 8769939a9c3SJeeja KP struct skl_module_cfg *mconfig) 877beb73b26SJeeja KP { 878beb73b26SJeeja KP u16 module_config_size = 0; 879beb73b26SJeeja KP void *param_data = NULL; 880beb73b26SJeeja KP int ret; 881beb73b26SJeeja KP struct skl_ipc_init_instance_msg msg; 882beb73b26SJeeja KP 883beb73b26SJeeja KP dev_dbg(ctx->dev, "%s: module_id = %d instance=%d\n", __func__, 884ef2a352cSDharageswari R mconfig->id.module_id, mconfig->id.pvt_id); 885beb73b26SJeeja KP 886beb73b26SJeeja KP if (mconfig->pipe->state != SKL_PIPE_CREATED) { 887beb73b26SJeeja KP dev_err(ctx->dev, "Pipe not created state= %d pipe_id= %d\n", 888beb73b26SJeeja KP mconfig->pipe->state, mconfig->pipe->ppl_id); 889beb73b26SJeeja KP return -EIO; 890beb73b26SJeeja KP } 891beb73b26SJeeja KP 892beb73b26SJeeja KP ret = skl_set_module_format(ctx, mconfig, 893beb73b26SJeeja KP &module_config_size, ¶m_data); 894beb73b26SJeeja KP if (ret < 0) { 895beb73b26SJeeja KP dev_err(ctx->dev, "Failed to set module format ret=%d\n", ret); 896beb73b26SJeeja KP return ret; 897beb73b26SJeeja KP } 898beb73b26SJeeja KP 899beb73b26SJeeja KP msg.module_id = mconfig->id.module_id; 900ef2a352cSDharageswari R msg.instance_id = mconfig->id.pvt_id; 901beb73b26SJeeja KP msg.ppl_instance_id = mconfig->pipe->ppl_id; 902beb73b26SJeeja KP msg.param_data_size = module_config_size; 903beb73b26SJeeja KP msg.core_id = mconfig->core_id; 9043d4006cdSSenthilnathan Veppur msg.domain = mconfig->domain; 905beb73b26SJeeja KP 906beb73b26SJeeja KP ret = skl_ipc_init_instance(&ctx->ipc, &msg, param_data); 907beb73b26SJeeja KP if (ret < 0) { 908beb73b26SJeeja KP dev_err(ctx->dev, "Failed to init instance ret=%d\n", ret); 909beb73b26SJeeja KP kfree(param_data); 910beb73b26SJeeja KP return ret; 911beb73b26SJeeja KP } 912beb73b26SJeeja KP mconfig->m_state = SKL_MODULE_INIT_DONE; 91376222d6dSMousumi Jana kfree(param_data); 914beb73b26SJeeja KP return ret; 915beb73b26SJeeja KP } 916beb73b26SJeeja KP 917beb73b26SJeeja KP static void skl_dump_bind_info(struct skl_sst *ctx, struct skl_module_cfg 918beb73b26SJeeja KP *src_module, struct skl_module_cfg *dst_module) 919beb73b26SJeeja KP { 920beb73b26SJeeja KP dev_dbg(ctx->dev, "%s: src module_id = %d src_instance=%d\n", 921ef2a352cSDharageswari R __func__, src_module->id.module_id, src_module->id.pvt_id); 922beb73b26SJeeja KP dev_dbg(ctx->dev, "%s: dst_module=%d dst_instacne=%d\n", __func__, 923ef2a352cSDharageswari R dst_module->id.module_id, dst_module->id.pvt_id); 924beb73b26SJeeja KP 925beb73b26SJeeja KP dev_dbg(ctx->dev, "src_module state = %d dst module state = %d\n", 926beb73b26SJeeja KP src_module->m_state, dst_module->m_state); 927beb73b26SJeeja KP } 928beb73b26SJeeja KP 929beb73b26SJeeja KP /* 930beb73b26SJeeja KP * On module freeup, we need to unbind the module with modules 931beb73b26SJeeja KP * it is already bind. 932beb73b26SJeeja KP * Find the pin allocated and unbind then using bind_unbind IPC 933beb73b26SJeeja KP */ 934beb73b26SJeeja KP int skl_unbind_modules(struct skl_sst *ctx, 935beb73b26SJeeja KP struct skl_module_cfg *src_mcfg, 936beb73b26SJeeja KP struct skl_module_cfg *dst_mcfg) 937beb73b26SJeeja KP { 938beb73b26SJeeja KP int ret; 939beb73b26SJeeja KP struct skl_ipc_bind_unbind_msg msg; 940beb73b26SJeeja KP struct skl_module_inst_id src_id = src_mcfg->id; 941beb73b26SJeeja KP struct skl_module_inst_id dst_id = dst_mcfg->id; 942beb73b26SJeeja KP int in_max = dst_mcfg->max_in_queue; 943beb73b26SJeeja KP int out_max = src_mcfg->max_out_queue; 9444f745708SJeeja KP int src_index, dst_index, src_pin_state, dst_pin_state; 945beb73b26SJeeja KP 946beb73b26SJeeja KP skl_dump_bind_info(ctx, src_mcfg, dst_mcfg); 947beb73b26SJeeja KP 948beb73b26SJeeja KP /* get src queue index */ 949beb73b26SJeeja KP src_index = skl_get_queue_index(src_mcfg->m_out_pin, dst_id, out_max); 950beb73b26SJeeja KP if (src_index < 0) 9519cf3049eSJeeja KP return 0; 952beb73b26SJeeja KP 9534f745708SJeeja KP msg.src_queue = src_index; 954beb73b26SJeeja KP 955beb73b26SJeeja KP /* get dst queue index */ 956beb73b26SJeeja KP dst_index = skl_get_queue_index(dst_mcfg->m_in_pin, src_id, in_max); 957beb73b26SJeeja KP if (dst_index < 0) 9589cf3049eSJeeja KP return 0; 959beb73b26SJeeja KP 9604f745708SJeeja KP msg.dst_queue = dst_index; 9614f745708SJeeja KP 9624f745708SJeeja KP src_pin_state = src_mcfg->m_out_pin[src_index].pin_state; 9634f745708SJeeja KP dst_pin_state = dst_mcfg->m_in_pin[dst_index].pin_state; 9644f745708SJeeja KP 9654f745708SJeeja KP if (src_pin_state != SKL_PIN_BIND_DONE || 9664f745708SJeeja KP dst_pin_state != SKL_PIN_BIND_DONE) 9674f745708SJeeja KP return 0; 968beb73b26SJeeja KP 969beb73b26SJeeja KP msg.module_id = src_mcfg->id.module_id; 970ef2a352cSDharageswari R msg.instance_id = src_mcfg->id.pvt_id; 971beb73b26SJeeja KP msg.dst_module_id = dst_mcfg->id.module_id; 972ef2a352cSDharageswari R msg.dst_instance_id = dst_mcfg->id.pvt_id; 973beb73b26SJeeja KP msg.bind = false; 974beb73b26SJeeja KP 975beb73b26SJeeja KP ret = skl_ipc_bind_unbind(&ctx->ipc, &msg); 976beb73b26SJeeja KP if (!ret) { 977beb73b26SJeeja KP /* free queue only if unbind is success */ 978beb73b26SJeeja KP skl_free_queue(src_mcfg->m_out_pin, src_index); 979beb73b26SJeeja KP skl_free_queue(dst_mcfg->m_in_pin, dst_index); 9804f745708SJeeja KP 9814f745708SJeeja KP /* 9824f745708SJeeja KP * check only if src module bind state, bind is 9834f745708SJeeja KP * always from src -> sink 9844f745708SJeeja KP */ 9854f745708SJeeja KP skl_clear_module_state(src_mcfg->m_out_pin, out_max, src_mcfg); 986beb73b26SJeeja KP } 987beb73b26SJeeja KP 988beb73b26SJeeja KP return ret; 989beb73b26SJeeja KP } 990beb73b26SJeeja KP 991beb73b26SJeeja KP /* 992beb73b26SJeeja KP * Once a module is instantiated it need to be 'bind' with other modules in 993beb73b26SJeeja KP * the pipeline. For binding we need to find the module pins which are bind 994beb73b26SJeeja KP * together 995beb73b26SJeeja KP * This function finds the pins and then sends bund_unbind IPC message to 996beb73b26SJeeja KP * DSP using IPC helper 997beb73b26SJeeja KP */ 998beb73b26SJeeja KP int skl_bind_modules(struct skl_sst *ctx, 999beb73b26SJeeja KP struct skl_module_cfg *src_mcfg, 1000beb73b26SJeeja KP struct skl_module_cfg *dst_mcfg) 1001beb73b26SJeeja KP { 1002beb73b26SJeeja KP int ret; 1003beb73b26SJeeja KP struct skl_ipc_bind_unbind_msg msg; 1004beb73b26SJeeja KP int in_max = dst_mcfg->max_in_queue; 1005beb73b26SJeeja KP int out_max = src_mcfg->max_out_queue; 1006beb73b26SJeeja KP int src_index, dst_index; 1007beb73b26SJeeja KP 1008beb73b26SJeeja KP skl_dump_bind_info(ctx, src_mcfg, dst_mcfg); 1009beb73b26SJeeja KP 10100c684c48SJeeja KP if (src_mcfg->m_state < SKL_MODULE_INIT_DONE || 1011beb73b26SJeeja KP dst_mcfg->m_state < SKL_MODULE_INIT_DONE) 1012beb73b26SJeeja KP return 0; 1013beb73b26SJeeja KP 10144f745708SJeeja KP src_index = skl_alloc_queue(src_mcfg->m_out_pin, dst_mcfg, out_max); 1015beb73b26SJeeja KP if (src_index < 0) 1016beb73b26SJeeja KP return -EINVAL; 1017beb73b26SJeeja KP 10184f745708SJeeja KP msg.src_queue = src_index; 10194f745708SJeeja KP dst_index = skl_alloc_queue(dst_mcfg->m_in_pin, src_mcfg, in_max); 1020beb73b26SJeeja KP if (dst_index < 0) { 1021beb73b26SJeeja KP skl_free_queue(src_mcfg->m_out_pin, src_index); 1022beb73b26SJeeja KP return -EINVAL; 1023beb73b26SJeeja KP } 1024beb73b26SJeeja KP 10254f745708SJeeja KP msg.dst_queue = dst_index; 1026beb73b26SJeeja KP 1027beb73b26SJeeja KP dev_dbg(ctx->dev, "src queue = %d dst queue =%d\n", 1028beb73b26SJeeja KP msg.src_queue, msg.dst_queue); 1029beb73b26SJeeja KP 1030beb73b26SJeeja KP msg.module_id = src_mcfg->id.module_id; 1031ef2a352cSDharageswari R msg.instance_id = src_mcfg->id.pvt_id; 1032beb73b26SJeeja KP msg.dst_module_id = dst_mcfg->id.module_id; 1033ef2a352cSDharageswari R msg.dst_instance_id = dst_mcfg->id.pvt_id; 1034beb73b26SJeeja KP msg.bind = true; 1035beb73b26SJeeja KP 1036beb73b26SJeeja KP ret = skl_ipc_bind_unbind(&ctx->ipc, &msg); 1037beb73b26SJeeja KP 1038beb73b26SJeeja KP if (!ret) { 1039beb73b26SJeeja KP src_mcfg->m_state = SKL_MODULE_BIND_DONE; 10404f745708SJeeja KP src_mcfg->m_out_pin[src_index].pin_state = SKL_PIN_BIND_DONE; 10414f745708SJeeja KP dst_mcfg->m_in_pin[dst_index].pin_state = SKL_PIN_BIND_DONE; 1042beb73b26SJeeja KP } else { 1043beb73b26SJeeja KP /* error case , if IPC fails, clear the queue index */ 1044beb73b26SJeeja KP skl_free_queue(src_mcfg->m_out_pin, src_index); 1045beb73b26SJeeja KP skl_free_queue(dst_mcfg->m_in_pin, dst_index); 1046beb73b26SJeeja KP } 1047beb73b26SJeeja KP 1048beb73b26SJeeja KP return ret; 1049beb73b26SJeeja KP } 1050c9b1e834SJeeja KP 1051c9b1e834SJeeja KP static int skl_set_pipe_state(struct skl_sst *ctx, struct skl_pipe *pipe, 1052c9b1e834SJeeja KP enum skl_ipc_pipeline_state state) 1053c9b1e834SJeeja KP { 1054c9b1e834SJeeja KP dev_dbg(ctx->dev, "%s: pipe_satate = %d\n", __func__, state); 1055c9b1e834SJeeja KP 1056c9b1e834SJeeja KP return skl_ipc_set_pipeline_state(&ctx->ipc, pipe->ppl_id, state); 1057c9b1e834SJeeja KP } 1058c9b1e834SJeeja KP 1059c9b1e834SJeeja KP /* 1060c9b1e834SJeeja KP * A pipeline is a collection of modules. Before a module in instantiated a 1061c9b1e834SJeeja KP * pipeline needs to be created for it. 1062c9b1e834SJeeja KP * This function creates pipeline, by sending create pipeline IPC messages 1063c9b1e834SJeeja KP * to FW 1064c9b1e834SJeeja KP */ 1065c9b1e834SJeeja KP int skl_create_pipeline(struct skl_sst *ctx, struct skl_pipe *pipe) 1066c9b1e834SJeeja KP { 1067c9b1e834SJeeja KP int ret; 1068c9b1e834SJeeja KP 1069c9b1e834SJeeja KP dev_dbg(ctx->dev, "%s: pipe_id = %d\n", __func__, pipe->ppl_id); 1070c9b1e834SJeeja KP 1071c9b1e834SJeeja KP ret = skl_ipc_create_pipeline(&ctx->ipc, pipe->memory_pages, 10728a0cb236SVinod Koul pipe->pipe_priority, pipe->ppl_id, 10738a0cb236SVinod Koul pipe->lp_mode); 1074c9b1e834SJeeja KP if (ret < 0) { 1075c9b1e834SJeeja KP dev_err(ctx->dev, "Failed to create pipeline\n"); 1076c9b1e834SJeeja KP return ret; 1077c9b1e834SJeeja KP } 1078c9b1e834SJeeja KP 1079c9b1e834SJeeja KP pipe->state = SKL_PIPE_CREATED; 1080c9b1e834SJeeja KP 1081c9b1e834SJeeja KP return 0; 1082c9b1e834SJeeja KP } 1083c9b1e834SJeeja KP 1084c9b1e834SJeeja KP /* 1085c9b1e834SJeeja KP * A pipeline needs to be deleted on cleanup. If a pipeline is running, then 1086c9b1e834SJeeja KP * pause the pipeline first and then delete it 1087c9b1e834SJeeja KP * The pipe delete is done by sending delete pipeline IPC. DSP will stop the 1088c9b1e834SJeeja KP * DMA engines and releases resources 1089c9b1e834SJeeja KP */ 1090c9b1e834SJeeja KP int skl_delete_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) 1091c9b1e834SJeeja KP { 1092c9b1e834SJeeja KP int ret; 1093c9b1e834SJeeja KP 1094c9b1e834SJeeja KP dev_dbg(ctx->dev, "%s: pipe = %d\n", __func__, pipe->ppl_id); 1095c9b1e834SJeeja KP 10961ae7ca04SDharageswari R /* If pipe is started, do stop the pipe in FW. */ 10976914968bSJeeja KP if (pipe->state >= SKL_PIPE_STARTED) { 1098c9b1e834SJeeja KP ret = skl_set_pipe_state(ctx, pipe, PPL_PAUSED); 1099c9b1e834SJeeja KP if (ret < 0) { 1100c9b1e834SJeeja KP dev_err(ctx->dev, "Failed to stop pipeline\n"); 1101c9b1e834SJeeja KP return ret; 1102c9b1e834SJeeja KP } 1103c9b1e834SJeeja KP 1104c9b1e834SJeeja KP pipe->state = SKL_PIPE_PAUSED; 11051ae7ca04SDharageswari R } 11061ae7ca04SDharageswari R 1107c9b1e834SJeeja KP /* If pipe was not created in FW, do not try to delete it */ 1108c9b1e834SJeeja KP if (pipe->state < SKL_PIPE_CREATED) 1109c9b1e834SJeeja KP return 0; 1110c9b1e834SJeeja KP 1111c9b1e834SJeeja KP ret = skl_ipc_delete_pipeline(&ctx->ipc, pipe->ppl_id); 11121ae7ca04SDharageswari R if (ret < 0) { 1113c9b1e834SJeeja KP dev_err(ctx->dev, "Failed to delete pipeline\n"); 11141ae7ca04SDharageswari R return ret; 11151ae7ca04SDharageswari R } 1116d2c7db85SJeeja KP 1117d2c7db85SJeeja KP pipe->state = SKL_PIPE_INVALID; 1118c9b1e834SJeeja KP 1119c9b1e834SJeeja KP return ret; 1120c9b1e834SJeeja KP } 1121c9b1e834SJeeja KP 1122c9b1e834SJeeja KP /* 1123c9b1e834SJeeja KP * A pipeline is also a scheduling entity in DSP which can be run, stopped 1124c9b1e834SJeeja KP * For processing data the pipe need to be run by sending IPC set pipe state 1125c9b1e834SJeeja KP * to DSP 1126c9b1e834SJeeja KP */ 1127c9b1e834SJeeja KP int skl_run_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) 1128c9b1e834SJeeja KP { 1129c9b1e834SJeeja KP int ret; 1130c9b1e834SJeeja KP 1131c9b1e834SJeeja KP dev_dbg(ctx->dev, "%s: pipe = %d\n", __func__, pipe->ppl_id); 1132c9b1e834SJeeja KP 1133c9b1e834SJeeja KP /* If pipe was not created in FW, do not try to pause or delete */ 1134c9b1e834SJeeja KP if (pipe->state < SKL_PIPE_CREATED) 1135c9b1e834SJeeja KP return 0; 1136c9b1e834SJeeja KP 1137c9b1e834SJeeja KP /* Pipe has to be paused before it is started */ 1138c9b1e834SJeeja KP ret = skl_set_pipe_state(ctx, pipe, PPL_PAUSED); 1139c9b1e834SJeeja KP if (ret < 0) { 1140c9b1e834SJeeja KP dev_err(ctx->dev, "Failed to pause pipe\n"); 1141c9b1e834SJeeja KP return ret; 1142c9b1e834SJeeja KP } 1143c9b1e834SJeeja KP 1144c9b1e834SJeeja KP pipe->state = SKL_PIPE_PAUSED; 1145c9b1e834SJeeja KP 1146c9b1e834SJeeja KP ret = skl_set_pipe_state(ctx, pipe, PPL_RUNNING); 1147c9b1e834SJeeja KP if (ret < 0) { 1148c9b1e834SJeeja KP dev_err(ctx->dev, "Failed to start pipe\n"); 1149c9b1e834SJeeja KP return ret; 1150c9b1e834SJeeja KP } 1151c9b1e834SJeeja KP 1152c9b1e834SJeeja KP pipe->state = SKL_PIPE_STARTED; 1153c9b1e834SJeeja KP 1154c9b1e834SJeeja KP return 0; 1155c9b1e834SJeeja KP } 1156c9b1e834SJeeja KP 1157c9b1e834SJeeja KP /* 1158c9b1e834SJeeja KP * Stop the pipeline by sending set pipe state IPC 1159c9b1e834SJeeja KP * DSP doesnt implement stop so we always send pause message 1160c9b1e834SJeeja KP */ 1161c9b1e834SJeeja KP int skl_stop_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) 1162c9b1e834SJeeja KP { 1163c9b1e834SJeeja KP int ret; 1164c9b1e834SJeeja KP 1165c9b1e834SJeeja KP dev_dbg(ctx->dev, "In %s pipe=%d\n", __func__, pipe->ppl_id); 1166c9b1e834SJeeja KP 1167c9b1e834SJeeja KP /* If pipe was not created in FW, do not try to pause or delete */ 1168c9b1e834SJeeja KP if (pipe->state < SKL_PIPE_PAUSED) 1169c9b1e834SJeeja KP return 0; 1170c9b1e834SJeeja KP 1171c9b1e834SJeeja KP ret = skl_set_pipe_state(ctx, pipe, PPL_PAUSED); 1172c9b1e834SJeeja KP if (ret < 0) { 1173c9b1e834SJeeja KP dev_dbg(ctx->dev, "Failed to stop pipe\n"); 1174c9b1e834SJeeja KP return ret; 1175c9b1e834SJeeja KP } 1176c9b1e834SJeeja KP 1177353f72aaSJeeja KP pipe->state = SKL_PIPE_PAUSED; 1178c9b1e834SJeeja KP 1179c9b1e834SJeeja KP return 0; 1180c9b1e834SJeeja KP } 11819939a9c3SJeeja KP 11822004432fSJeeja KP /* 11832004432fSJeeja KP * Reset the pipeline by sending set pipe state IPC this will reset the DMA 11842004432fSJeeja KP * from the DSP side 11852004432fSJeeja KP */ 11862004432fSJeeja KP int skl_reset_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) 11872004432fSJeeja KP { 11882004432fSJeeja KP int ret; 11892004432fSJeeja KP 11902004432fSJeeja KP /* If pipe was not created in FW, do not try to pause or delete */ 11912004432fSJeeja KP if (pipe->state < SKL_PIPE_PAUSED) 11922004432fSJeeja KP return 0; 11932004432fSJeeja KP 11942004432fSJeeja KP ret = skl_set_pipe_state(ctx, pipe, PPL_RESET); 11952004432fSJeeja KP if (ret < 0) { 11962004432fSJeeja KP dev_dbg(ctx->dev, "Failed to reset pipe ret=%d\n", ret); 11972004432fSJeeja KP return ret; 11982004432fSJeeja KP } 11992004432fSJeeja KP 12002004432fSJeeja KP pipe->state = SKL_PIPE_RESET; 12012004432fSJeeja KP 12022004432fSJeeja KP return 0; 12032004432fSJeeja KP } 12042004432fSJeeja KP 12059939a9c3SJeeja KP /* Algo parameter set helper function */ 12069939a9c3SJeeja KP int skl_set_module_params(struct skl_sst *ctx, u32 *params, int size, 12079939a9c3SJeeja KP u32 param_id, struct skl_module_cfg *mcfg) 12089939a9c3SJeeja KP { 12099939a9c3SJeeja KP struct skl_ipc_large_config_msg msg; 12109939a9c3SJeeja KP 12119939a9c3SJeeja KP msg.module_id = mcfg->id.module_id; 1212ef2a352cSDharageswari R msg.instance_id = mcfg->id.pvt_id; 12139939a9c3SJeeja KP msg.param_data_size = size; 12149939a9c3SJeeja KP msg.large_param_id = param_id; 12159939a9c3SJeeja KP 12169939a9c3SJeeja KP return skl_ipc_set_large_config(&ctx->ipc, &msg, params); 12179939a9c3SJeeja KP } 12187d9f2911SOmair M Abdullah 12197d9f2911SOmair M Abdullah int skl_get_module_params(struct skl_sst *ctx, u32 *params, int size, 12207d9f2911SOmair M Abdullah u32 param_id, struct skl_module_cfg *mcfg) 12217d9f2911SOmair M Abdullah { 12227d9f2911SOmair M Abdullah struct skl_ipc_large_config_msg msg; 12237d9f2911SOmair M Abdullah 12247d9f2911SOmair M Abdullah msg.module_id = mcfg->id.module_id; 1225ef2a352cSDharageswari R msg.instance_id = mcfg->id.pvt_id; 12267d9f2911SOmair M Abdullah msg.param_data_size = size; 12277d9f2911SOmair M Abdullah msg.large_param_id = param_id; 12287d9f2911SOmair M Abdullah 12297d9f2911SOmair M Abdullah return skl_ipc_get_large_config(&ctx->ipc, &msg, params); 12307d9f2911SOmair M Abdullah } 1231