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 */ 614e10996bSJeeja KP static 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 75d255b095SJeeja KP int skl_init_dsp(struct skl *skl) 76d255b095SJeeja KP { 77d255b095SJeeja KP void __iomem *mmio_base; 78d255b095SJeeja KP struct hdac_ext_bus *ebus = &skl->ebus; 79d255b095SJeeja KP struct hdac_bus *bus = ebus_to_hbus(ebus); 80d255b095SJeeja KP int irq = bus->irq; 81d255b095SJeeja KP struct skl_dsp_loader_ops loader_ops; 82d255b095SJeeja KP int ret; 83d255b095SJeeja KP 84d255b095SJeeja KP loader_ops.alloc_dma_buf = skl_alloc_dma_buf; 85d255b095SJeeja KP loader_ops.free_dma_buf = skl_free_dma_buf; 86d255b095SJeeja KP 87d255b095SJeeja KP /* enable ppcap interrupt */ 88d255b095SJeeja KP snd_hdac_ext_bus_ppcap_enable(&skl->ebus, true); 89d255b095SJeeja KP snd_hdac_ext_bus_ppcap_int_enable(&skl->ebus, true); 90d255b095SJeeja KP 91d255b095SJeeja KP /* read the BAR of the ADSP MMIO */ 92d255b095SJeeja KP mmio_base = pci_ioremap_bar(skl->pci, 4); 93d255b095SJeeja KP if (mmio_base == NULL) { 94d255b095SJeeja KP dev_err(bus->dev, "ioremap error\n"); 95d255b095SJeeja KP return -ENXIO; 96d255b095SJeeja KP } 97d255b095SJeeja KP 98d255b095SJeeja KP ret = skl_sst_dsp_init(bus->dev, mmio_base, irq, 99aecf6fd8SVinod Koul skl->fw_name, loader_ops, &skl->skl_sst); 1002ac454ffSJeeja KP if (ret < 0) 1012ac454ffSJeeja KP return ret; 1022ac454ffSJeeja KP 1034e10996bSJeeja KP skl_dsp_enable_notification(skl->skl_sst, false); 104d255b095SJeeja KP dev_dbg(bus->dev, "dsp registration status=%d\n", ret); 105d255b095SJeeja KP 106d255b095SJeeja KP return ret; 107d255b095SJeeja KP } 108d255b095SJeeja KP 109d255b095SJeeja KP void skl_free_dsp(struct skl *skl) 110d255b095SJeeja KP { 111d255b095SJeeja KP struct hdac_ext_bus *ebus = &skl->ebus; 112d255b095SJeeja KP struct hdac_bus *bus = ebus_to_hbus(ebus); 113d255b095SJeeja KP struct skl_sst *ctx = skl->skl_sst; 114d255b095SJeeja KP 115d255b095SJeeja KP /* disable ppcap interrupt */ 116d255b095SJeeja KP snd_hdac_ext_bus_ppcap_int_enable(&skl->ebus, false); 117d255b095SJeeja KP 118d255b095SJeeja KP skl_sst_dsp_cleanup(bus->dev, ctx); 119d255b095SJeeja KP if (ctx->dsp->addr.lpe) 120d255b095SJeeja KP iounmap(ctx->dsp->addr.lpe); 121d255b095SJeeja KP } 122d255b095SJeeja KP 123d255b095SJeeja KP int skl_suspend_dsp(struct skl *skl) 124d255b095SJeeja KP { 125d255b095SJeeja KP struct skl_sst *ctx = skl->skl_sst; 126d255b095SJeeja KP int ret; 127d255b095SJeeja KP 128d255b095SJeeja KP /* if ppcap is not supported return 0 */ 129d255b095SJeeja KP if (!skl->ebus.ppcap) 130d255b095SJeeja KP return 0; 131d255b095SJeeja KP 132d255b095SJeeja KP ret = skl_dsp_sleep(ctx->dsp); 133d255b095SJeeja KP if (ret < 0) 134d255b095SJeeja KP return ret; 135d255b095SJeeja KP 136d255b095SJeeja KP /* disable ppcap interrupt */ 137d255b095SJeeja KP snd_hdac_ext_bus_ppcap_int_enable(&skl->ebus, false); 138d255b095SJeeja KP snd_hdac_ext_bus_ppcap_enable(&skl->ebus, false); 139d255b095SJeeja KP 140d255b095SJeeja KP return 0; 141d255b095SJeeja KP } 142d255b095SJeeja KP 143d255b095SJeeja KP int skl_resume_dsp(struct skl *skl) 144d255b095SJeeja KP { 145d255b095SJeeja KP struct skl_sst *ctx = skl->skl_sst; 1464e10996bSJeeja KP int ret; 147d255b095SJeeja KP 148d255b095SJeeja KP /* if ppcap is not supported return 0 */ 149d255b095SJeeja KP if (!skl->ebus.ppcap) 150d255b095SJeeja KP return 0; 151d255b095SJeeja KP 152d255b095SJeeja KP /* enable ppcap interrupt */ 153d255b095SJeeja KP snd_hdac_ext_bus_ppcap_enable(&skl->ebus, true); 154d255b095SJeeja KP snd_hdac_ext_bus_ppcap_int_enable(&skl->ebus, true); 155d255b095SJeeja KP 1564e10996bSJeeja KP ret = skl_dsp_wake(ctx->dsp); 1574e10996bSJeeja KP if (ret < 0) 1584e10996bSJeeja KP return ret; 1594e10996bSJeeja KP 1604e10996bSJeeja KP skl_dsp_enable_notification(skl->skl_sst, false); 1614e10996bSJeeja KP return ret; 162d255b095SJeeja KP } 16323db472bSJeeja KP 16423db472bSJeeja KP enum skl_bitdepth skl_get_bit_depth(int params) 16523db472bSJeeja KP { 16623db472bSJeeja KP switch (params) { 16723db472bSJeeja KP case 8: 16823db472bSJeeja KP return SKL_DEPTH_8BIT; 16923db472bSJeeja KP 17023db472bSJeeja KP case 16: 17123db472bSJeeja KP return SKL_DEPTH_16BIT; 17223db472bSJeeja KP 17323db472bSJeeja KP case 24: 17423db472bSJeeja KP return SKL_DEPTH_24BIT; 17523db472bSJeeja KP 17623db472bSJeeja KP case 32: 17723db472bSJeeja KP return SKL_DEPTH_32BIT; 17823db472bSJeeja KP 17923db472bSJeeja KP default: 18023db472bSJeeja KP return SKL_DEPTH_INVALID; 18123db472bSJeeja KP 18223db472bSJeeja KP } 18323db472bSJeeja KP } 18423db472bSJeeja KP 18523db472bSJeeja KP /* 18623db472bSJeeja KP * Each module in DSP expects a base module configuration, which consists of 18723db472bSJeeja KP * PCM format information, which we calculate in driver and resource values 18823db472bSJeeja KP * which are read from widget information passed through topology binary 18923db472bSJeeja KP * This is send when we create a module with INIT_INSTANCE IPC msg 19023db472bSJeeja KP */ 19123db472bSJeeja KP static void skl_set_base_module_format(struct skl_sst *ctx, 19223db472bSJeeja KP struct skl_module_cfg *mconfig, 19323db472bSJeeja KP struct skl_base_cfg *base_cfg) 19423db472bSJeeja KP { 1954cd9899fSHardik T Shah struct skl_module_fmt *format = &mconfig->in_fmt[0]; 19623db472bSJeeja KP 19723db472bSJeeja KP base_cfg->audio_fmt.number_of_channels = (u8)format->channels; 19823db472bSJeeja KP 19923db472bSJeeja KP base_cfg->audio_fmt.s_freq = format->s_freq; 20023db472bSJeeja KP base_cfg->audio_fmt.bit_depth = format->bit_depth; 20123db472bSJeeja KP base_cfg->audio_fmt.valid_bit_depth = format->valid_bit_depth; 20223db472bSJeeja KP base_cfg->audio_fmt.ch_cfg = format->ch_cfg; 20323db472bSJeeja KP 20423db472bSJeeja KP dev_dbg(ctx->dev, "bit_depth=%x valid_bd=%x ch_config=%x\n", 20523db472bSJeeja KP format->bit_depth, format->valid_bit_depth, 20623db472bSJeeja KP format->ch_cfg); 20723db472bSJeeja KP 2083e81f1a3SJeeja KP base_cfg->audio_fmt.channel_map = format->ch_map; 20923db472bSJeeja KP 2103e81f1a3SJeeja KP base_cfg->audio_fmt.interleaving = format->interleaving_style; 21123db472bSJeeja KP 21223db472bSJeeja KP base_cfg->cps = mconfig->mcps; 21323db472bSJeeja KP base_cfg->ibs = mconfig->ibs; 21423db472bSJeeja KP base_cfg->obs = mconfig->obs; 21523db472bSJeeja KP } 21623db472bSJeeja KP 21723db472bSJeeja KP /* 21823db472bSJeeja KP * Copies copier capabilities into copier module and updates copier module 21923db472bSJeeja KP * config size. 22023db472bSJeeja KP */ 22123db472bSJeeja KP static void skl_copy_copier_caps(struct skl_module_cfg *mconfig, 22223db472bSJeeja KP struct skl_cpr_cfg *cpr_mconfig) 22323db472bSJeeja KP { 22423db472bSJeeja KP if (mconfig->formats_config.caps_size == 0) 22523db472bSJeeja KP return; 22623db472bSJeeja KP 22723db472bSJeeja KP memcpy(cpr_mconfig->gtw_cfg.config_data, 22823db472bSJeeja KP mconfig->formats_config.caps, 22923db472bSJeeja KP mconfig->formats_config.caps_size); 23023db472bSJeeja KP 23123db472bSJeeja KP cpr_mconfig->gtw_cfg.config_length = 23223db472bSJeeja KP (mconfig->formats_config.caps_size) / 4; 23323db472bSJeeja KP } 23423db472bSJeeja KP 235bfa764acSJeeja KP #define SKL_NON_GATEWAY_CPR_NODE_ID 0xFFFFFFFF 23623db472bSJeeja KP /* 23723db472bSJeeja KP * Calculate the gatewat settings required for copier module, type of 23823db472bSJeeja KP * gateway and index of gateway to use 23923db472bSJeeja KP */ 24023db472bSJeeja KP static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx, 24123db472bSJeeja KP struct skl_module_cfg *mconfig, 24223db472bSJeeja KP struct skl_cpr_cfg *cpr_mconfig) 24323db472bSJeeja KP { 24423db472bSJeeja KP union skl_connector_node_id node_id = {0}; 245d7b18813SJeeja KP union skl_ssp_dma_node ssp_node = {0}; 24623db472bSJeeja KP struct skl_pipe_params *params = mconfig->pipe->p_params; 24723db472bSJeeja KP 24823db472bSJeeja KP switch (mconfig->dev_type) { 24923db472bSJeeja KP case SKL_DEVICE_BT: 25023db472bSJeeja KP node_id.node.dma_type = 25123db472bSJeeja KP (SKL_CONN_SOURCE == mconfig->hw_conn_type) ? 25223db472bSJeeja KP SKL_DMA_I2S_LINK_OUTPUT_CLASS : 25323db472bSJeeja KP SKL_DMA_I2S_LINK_INPUT_CLASS; 25423db472bSJeeja KP node_id.node.vindex = params->host_dma_id + 25523db472bSJeeja KP (mconfig->vbus_id << 3); 25623db472bSJeeja KP break; 25723db472bSJeeja KP 25823db472bSJeeja KP case SKL_DEVICE_I2S: 25923db472bSJeeja KP node_id.node.dma_type = 26023db472bSJeeja KP (SKL_CONN_SOURCE == mconfig->hw_conn_type) ? 26123db472bSJeeja KP SKL_DMA_I2S_LINK_OUTPUT_CLASS : 26223db472bSJeeja KP SKL_DMA_I2S_LINK_INPUT_CLASS; 263d7b18813SJeeja KP ssp_node.dma_node.time_slot_index = mconfig->time_slot; 264d7b18813SJeeja KP ssp_node.dma_node.i2s_instance = mconfig->vbus_id; 265d7b18813SJeeja KP node_id.node.vindex = ssp_node.val; 26623db472bSJeeja KP break; 26723db472bSJeeja KP 26823db472bSJeeja KP case SKL_DEVICE_DMIC: 26923db472bSJeeja KP node_id.node.dma_type = SKL_DMA_DMIC_LINK_INPUT_CLASS; 27023db472bSJeeja KP node_id.node.vindex = mconfig->vbus_id + 27123db472bSJeeja KP (mconfig->time_slot); 27223db472bSJeeja KP break; 27323db472bSJeeja KP 27423db472bSJeeja KP case SKL_DEVICE_HDALINK: 27523db472bSJeeja KP node_id.node.dma_type = 27623db472bSJeeja KP (SKL_CONN_SOURCE == mconfig->hw_conn_type) ? 27723db472bSJeeja KP SKL_DMA_HDA_LINK_OUTPUT_CLASS : 27823db472bSJeeja KP SKL_DMA_HDA_LINK_INPUT_CLASS; 27923db472bSJeeja KP node_id.node.vindex = params->link_dma_id; 28023db472bSJeeja KP break; 28123db472bSJeeja KP 282bfa764acSJeeja KP case SKL_DEVICE_HDAHOST: 28323db472bSJeeja KP node_id.node.dma_type = 28423db472bSJeeja KP (SKL_CONN_SOURCE == mconfig->hw_conn_type) ? 28523db472bSJeeja KP SKL_DMA_HDA_HOST_OUTPUT_CLASS : 28623db472bSJeeja KP SKL_DMA_HDA_HOST_INPUT_CLASS; 28723db472bSJeeja KP node_id.node.vindex = params->host_dma_id; 28823db472bSJeeja KP break; 289bfa764acSJeeja KP 290bfa764acSJeeja KP default: 291bfa764acSJeeja KP cpr_mconfig->gtw_cfg.node_id = SKL_NON_GATEWAY_CPR_NODE_ID; 292bfa764acSJeeja KP cpr_mconfig->cpr_feature_mask = 0; 293bfa764acSJeeja KP return; 29423db472bSJeeja KP } 29523db472bSJeeja KP 29623db472bSJeeja KP cpr_mconfig->gtw_cfg.node_id = node_id.val; 29723db472bSJeeja KP 29823db472bSJeeja KP if (SKL_CONN_SOURCE == mconfig->hw_conn_type) 29923db472bSJeeja KP cpr_mconfig->gtw_cfg.dma_buffer_size = 2 * mconfig->obs; 30023db472bSJeeja KP else 30123db472bSJeeja KP cpr_mconfig->gtw_cfg.dma_buffer_size = 2 * mconfig->ibs; 30223db472bSJeeja KP 30323db472bSJeeja KP cpr_mconfig->cpr_feature_mask = 0; 30423db472bSJeeja KP cpr_mconfig->gtw_cfg.config_length = 0; 30523db472bSJeeja KP 30623db472bSJeeja KP skl_copy_copier_caps(mconfig, cpr_mconfig); 30723db472bSJeeja KP } 30823db472bSJeeja KP 30923db472bSJeeja KP static void skl_setup_out_format(struct skl_sst *ctx, 31023db472bSJeeja KP struct skl_module_cfg *mconfig, 31123db472bSJeeja KP struct skl_audio_data_format *out_fmt) 31223db472bSJeeja KP { 3134cd9899fSHardik T Shah struct skl_module_fmt *format = &mconfig->out_fmt[0]; 31423db472bSJeeja KP 31523db472bSJeeja KP out_fmt->number_of_channels = (u8)format->channels; 31623db472bSJeeja KP out_fmt->s_freq = format->s_freq; 31723db472bSJeeja KP out_fmt->bit_depth = format->bit_depth; 31823db472bSJeeja KP out_fmt->valid_bit_depth = format->valid_bit_depth; 31923db472bSJeeja KP out_fmt->ch_cfg = format->ch_cfg; 32023db472bSJeeja KP 3213e81f1a3SJeeja KP out_fmt->channel_map = format->ch_map; 3223e81f1a3SJeeja KP out_fmt->interleaving = format->interleaving_style; 3233e81f1a3SJeeja KP out_fmt->sample_type = format->sample_type; 32423db472bSJeeja KP 32523db472bSJeeja KP dev_dbg(ctx->dev, "copier out format chan=%d fre=%d bitdepth=%d\n", 32623db472bSJeeja KP out_fmt->number_of_channels, format->s_freq, format->bit_depth); 32723db472bSJeeja KP } 32823db472bSJeeja KP 32923db472bSJeeja KP /* 330a0ffe48bSHardik T Shah * DSP needs SRC module for frequency conversion, SRC takes base module 331a0ffe48bSHardik T Shah * configuration and the target frequency as extra parameter passed as src 332a0ffe48bSHardik T Shah * config 333a0ffe48bSHardik T Shah */ 334a0ffe48bSHardik T Shah static void skl_set_src_format(struct skl_sst *ctx, 335a0ffe48bSHardik T Shah struct skl_module_cfg *mconfig, 336a0ffe48bSHardik T Shah struct skl_src_module_cfg *src_mconfig) 337a0ffe48bSHardik T Shah { 3384cd9899fSHardik T Shah struct skl_module_fmt *fmt = &mconfig->out_fmt[0]; 339a0ffe48bSHardik T Shah 340a0ffe48bSHardik T Shah skl_set_base_module_format(ctx, mconfig, 341a0ffe48bSHardik T Shah (struct skl_base_cfg *)src_mconfig); 342a0ffe48bSHardik T Shah 343a0ffe48bSHardik T Shah src_mconfig->src_cfg = fmt->s_freq; 344a0ffe48bSHardik T Shah } 345a0ffe48bSHardik T Shah 346a0ffe48bSHardik T Shah /* 347a0ffe48bSHardik T Shah * DSP needs updown module to do channel conversion. updown module take base 348a0ffe48bSHardik T Shah * module configuration and channel configuration 349a0ffe48bSHardik T Shah * It also take coefficients and now we have defaults applied here 350a0ffe48bSHardik T Shah */ 351a0ffe48bSHardik T Shah static void skl_set_updown_mixer_format(struct skl_sst *ctx, 352a0ffe48bSHardik T Shah struct skl_module_cfg *mconfig, 353a0ffe48bSHardik T Shah struct skl_up_down_mixer_cfg *mixer_mconfig) 354a0ffe48bSHardik T Shah { 3554cd9899fSHardik T Shah struct skl_module_fmt *fmt = &mconfig->out_fmt[0]; 356a0ffe48bSHardik T Shah int i = 0; 357a0ffe48bSHardik T Shah 358a0ffe48bSHardik T Shah skl_set_base_module_format(ctx, mconfig, 359a0ffe48bSHardik T Shah (struct skl_base_cfg *)mixer_mconfig); 360a0ffe48bSHardik T Shah mixer_mconfig->out_ch_cfg = fmt->ch_cfg; 361a0ffe48bSHardik T Shah 362a0ffe48bSHardik T Shah /* Select F/W default coefficient */ 363a0ffe48bSHardik T Shah mixer_mconfig->coeff_sel = 0x0; 364a0ffe48bSHardik T Shah 365a0ffe48bSHardik T Shah /* User coeff, don't care since we are selecting F/W defaults */ 366a0ffe48bSHardik T Shah for (i = 0; i < UP_DOWN_MIXER_MAX_COEFF; i++) 367a0ffe48bSHardik T Shah mixer_mconfig->coeff[i] = 0xDEADBEEF; 368a0ffe48bSHardik T Shah } 369a0ffe48bSHardik T Shah 370a0ffe48bSHardik T Shah /* 37123db472bSJeeja KP * 'copier' is DSP internal module which copies data from Host DMA (HDA host 37223db472bSJeeja KP * dma) or link (hda link, SSP, PDM) 37323db472bSJeeja KP * Here we calculate the copier module parameters, like PCM format, output 37423db472bSJeeja KP * format, gateway settings 37523db472bSJeeja KP * copier_module_config is sent as input buffer with INIT_INSTANCE IPC msg 37623db472bSJeeja KP */ 37723db472bSJeeja KP static void skl_set_copier_format(struct skl_sst *ctx, 37823db472bSJeeja KP struct skl_module_cfg *mconfig, 37923db472bSJeeja KP struct skl_cpr_cfg *cpr_mconfig) 38023db472bSJeeja KP { 38123db472bSJeeja KP struct skl_audio_data_format *out_fmt = &cpr_mconfig->out_fmt; 38223db472bSJeeja KP struct skl_base_cfg *base_cfg = (struct skl_base_cfg *)cpr_mconfig; 38323db472bSJeeja KP 38423db472bSJeeja KP skl_set_base_module_format(ctx, mconfig, base_cfg); 38523db472bSJeeja KP 38623db472bSJeeja KP skl_setup_out_format(ctx, mconfig, out_fmt); 38723db472bSJeeja KP skl_setup_cpr_gateway_cfg(ctx, mconfig, cpr_mconfig); 38823db472bSJeeja KP } 38923db472bSJeeja KP 39023db472bSJeeja KP static u16 skl_get_module_param_size(struct skl_sst *ctx, 39123db472bSJeeja KP struct skl_module_cfg *mconfig) 39223db472bSJeeja KP { 39323db472bSJeeja KP u16 param_size; 39423db472bSJeeja KP 39523db472bSJeeja KP switch (mconfig->m_type) { 39623db472bSJeeja KP case SKL_MODULE_TYPE_COPIER: 39723db472bSJeeja KP param_size = sizeof(struct skl_cpr_cfg); 39823db472bSJeeja KP param_size += mconfig->formats_config.caps_size; 39923db472bSJeeja KP return param_size; 40023db472bSJeeja KP 401a0ffe48bSHardik T Shah case SKL_MODULE_TYPE_SRCINT: 402a0ffe48bSHardik T Shah return sizeof(struct skl_src_module_cfg); 403a0ffe48bSHardik T Shah 404a0ffe48bSHardik T Shah case SKL_MODULE_TYPE_UPDWMIX: 405a0ffe48bSHardik T Shah return sizeof(struct skl_up_down_mixer_cfg); 406a0ffe48bSHardik T Shah 40723db472bSJeeja KP default: 40823db472bSJeeja KP /* 40923db472bSJeeja KP * return only base cfg when no specific module type is 41023db472bSJeeja KP * specified 41123db472bSJeeja KP */ 41223db472bSJeeja KP return sizeof(struct skl_base_cfg); 41323db472bSJeeja KP } 41423db472bSJeeja KP 41523db472bSJeeja KP return 0; 41623db472bSJeeja KP } 41723db472bSJeeja KP 41823db472bSJeeja KP /* 419a0ffe48bSHardik T Shah * DSP firmware supports various modules like copier, SRC, updown etc. 420a0ffe48bSHardik T Shah * These modules required various parameters to be calculated and sent for 421a0ffe48bSHardik T Shah * the module initialization to DSP. By default a generic module needs only 422a0ffe48bSHardik T Shah * base module format configuration 42323db472bSJeeja KP */ 424a0ffe48bSHardik T Shah 42523db472bSJeeja KP static int skl_set_module_format(struct skl_sst *ctx, 42623db472bSJeeja KP struct skl_module_cfg *module_config, 42723db472bSJeeja KP u16 *module_config_size, 42823db472bSJeeja KP void **param_data) 42923db472bSJeeja KP { 43023db472bSJeeja KP u16 param_size; 43123db472bSJeeja KP 43223db472bSJeeja KP param_size = skl_get_module_param_size(ctx, module_config); 43323db472bSJeeja KP 43423db472bSJeeja KP *param_data = kzalloc(param_size, GFP_KERNEL); 43523db472bSJeeja KP if (NULL == *param_data) 43623db472bSJeeja KP return -ENOMEM; 43723db472bSJeeja KP 43823db472bSJeeja KP *module_config_size = param_size; 43923db472bSJeeja KP 44023db472bSJeeja KP switch (module_config->m_type) { 44123db472bSJeeja KP case SKL_MODULE_TYPE_COPIER: 44223db472bSJeeja KP skl_set_copier_format(ctx, module_config, *param_data); 44323db472bSJeeja KP break; 44423db472bSJeeja KP 445a0ffe48bSHardik T Shah case SKL_MODULE_TYPE_SRCINT: 446a0ffe48bSHardik T Shah skl_set_src_format(ctx, module_config, *param_data); 447a0ffe48bSHardik T Shah break; 448a0ffe48bSHardik T Shah 449a0ffe48bSHardik T Shah case SKL_MODULE_TYPE_UPDWMIX: 450a0ffe48bSHardik T Shah skl_set_updown_mixer_format(ctx, module_config, *param_data); 451a0ffe48bSHardik T Shah break; 452a0ffe48bSHardik T Shah 45323db472bSJeeja KP default: 45423db472bSJeeja KP skl_set_base_module_format(ctx, module_config, *param_data); 45523db472bSJeeja KP break; 45623db472bSJeeja KP 45723db472bSJeeja KP } 45823db472bSJeeja KP 45923db472bSJeeja KP dev_dbg(ctx->dev, "Module type=%d config size: %d bytes\n", 46023db472bSJeeja KP module_config->id.module_id, param_size); 46123db472bSJeeja KP print_hex_dump(KERN_DEBUG, "Module params:", DUMP_PREFIX_OFFSET, 8, 4, 46223db472bSJeeja KP *param_data, param_size, false); 46323db472bSJeeja KP return 0; 46423db472bSJeeja KP } 46523db472bSJeeja KP 46623db472bSJeeja KP static int skl_get_queue_index(struct skl_module_pin *mpin, 46723db472bSJeeja KP struct skl_module_inst_id id, int max) 46823db472bSJeeja KP { 46923db472bSJeeja KP int i; 47023db472bSJeeja KP 47123db472bSJeeja KP for (i = 0; i < max; i++) { 47223db472bSJeeja KP if (mpin[i].id.module_id == id.module_id && 47323db472bSJeeja KP mpin[i].id.instance_id == id.instance_id) 47423db472bSJeeja KP return i; 47523db472bSJeeja KP } 47623db472bSJeeja KP 47723db472bSJeeja KP return -EINVAL; 47823db472bSJeeja KP } 47923db472bSJeeja KP 48023db472bSJeeja KP /* 48123db472bSJeeja KP * Allocates queue for each module. 48223db472bSJeeja KP * if dynamic, the pin_index is allocated 0 to max_pin. 48323db472bSJeeja KP * In static, the pin_index is fixed based on module_id and instance id 48423db472bSJeeja KP */ 48523db472bSJeeja KP static int skl_alloc_queue(struct skl_module_pin *mpin, 4864f745708SJeeja KP struct skl_module_cfg *tgt_cfg, int max) 48723db472bSJeeja KP { 48823db472bSJeeja KP int i; 4894f745708SJeeja KP struct skl_module_inst_id id = tgt_cfg->id; 49023db472bSJeeja KP /* 49123db472bSJeeja KP * if pin in dynamic, find first free pin 49223db472bSJeeja KP * otherwise find match module and instance id pin as topology will 49323db472bSJeeja KP * ensure a unique pin is assigned to this so no need to 49423db472bSJeeja KP * allocate/free 49523db472bSJeeja KP */ 49623db472bSJeeja KP for (i = 0; i < max; i++) { 49723db472bSJeeja KP if (mpin[i].is_dynamic) { 4984f745708SJeeja KP if (!mpin[i].in_use && 4994f745708SJeeja KP mpin[i].pin_state == SKL_PIN_UNBIND) { 5004f745708SJeeja KP 50123db472bSJeeja KP mpin[i].in_use = true; 50223db472bSJeeja KP mpin[i].id.module_id = id.module_id; 50323db472bSJeeja KP mpin[i].id.instance_id = id.instance_id; 5044f745708SJeeja KP mpin[i].tgt_mcfg = tgt_cfg; 50523db472bSJeeja KP return i; 50623db472bSJeeja KP } 50723db472bSJeeja KP } else { 50823db472bSJeeja KP if (mpin[i].id.module_id == id.module_id && 5094f745708SJeeja KP mpin[i].id.instance_id == id.instance_id && 5104f745708SJeeja KP mpin[i].pin_state == SKL_PIN_UNBIND) { 5114f745708SJeeja KP 5124f745708SJeeja KP mpin[i].tgt_mcfg = tgt_cfg; 51323db472bSJeeja KP return i; 51423db472bSJeeja KP } 51523db472bSJeeja KP } 5164f745708SJeeja KP } 51723db472bSJeeja KP 51823db472bSJeeja KP return -EINVAL; 51923db472bSJeeja KP } 52023db472bSJeeja KP 52123db472bSJeeja KP static void skl_free_queue(struct skl_module_pin *mpin, int q_index) 52223db472bSJeeja KP { 52323db472bSJeeja KP if (mpin[q_index].is_dynamic) { 52423db472bSJeeja KP mpin[q_index].in_use = false; 52523db472bSJeeja KP mpin[q_index].id.module_id = 0; 52623db472bSJeeja KP mpin[q_index].id.instance_id = 0; 52723db472bSJeeja KP } 5284f745708SJeeja KP mpin[q_index].pin_state = SKL_PIN_UNBIND; 5294f745708SJeeja KP mpin[q_index].tgt_mcfg = NULL; 5304f745708SJeeja KP } 5314f745708SJeeja KP 5324f745708SJeeja KP /* Module state will be set to unint, if all the out pin state is UNBIND */ 5334f745708SJeeja KP 5344f745708SJeeja KP static void skl_clear_module_state(struct skl_module_pin *mpin, int max, 5354f745708SJeeja KP struct skl_module_cfg *mcfg) 5364f745708SJeeja KP { 5374f745708SJeeja KP int i; 5384f745708SJeeja KP bool found = false; 5394f745708SJeeja KP 5404f745708SJeeja KP for (i = 0; i < max; i++) { 5414f745708SJeeja KP if (mpin[i].pin_state == SKL_PIN_UNBIND) 5424f745708SJeeja KP continue; 5434f745708SJeeja KP found = true; 5444f745708SJeeja KP break; 5454f745708SJeeja KP } 5464f745708SJeeja KP 5474f745708SJeeja KP if (!found) 5484f745708SJeeja KP mcfg->m_state = SKL_MODULE_UNINIT; 5494f745708SJeeja KP return; 55023db472bSJeeja KP } 551beb73b26SJeeja KP 552beb73b26SJeeja KP /* 553beb73b26SJeeja KP * A module needs to be instanataited in DSP. A mdoule is present in a 554beb73b26SJeeja KP * collection of module referred as a PIPE. 555beb73b26SJeeja KP * We first calculate the module format, based on module type and then 556beb73b26SJeeja KP * invoke the DSP by sending IPC INIT_INSTANCE using ipc helper 557beb73b26SJeeja KP */ 558beb73b26SJeeja KP int skl_init_module(struct skl_sst *ctx, 559beb73b26SJeeja KP struct skl_module_cfg *mconfig, char *param) 560beb73b26SJeeja KP { 561beb73b26SJeeja KP u16 module_config_size = 0; 562beb73b26SJeeja KP void *param_data = NULL; 563beb73b26SJeeja KP int ret; 564beb73b26SJeeja KP struct skl_ipc_init_instance_msg msg; 565beb73b26SJeeja KP 566beb73b26SJeeja KP dev_dbg(ctx->dev, "%s: module_id = %d instance=%d\n", __func__, 567beb73b26SJeeja KP mconfig->id.module_id, mconfig->id.instance_id); 568beb73b26SJeeja KP 569beb73b26SJeeja KP if (mconfig->pipe->state != SKL_PIPE_CREATED) { 570beb73b26SJeeja KP dev_err(ctx->dev, "Pipe not created state= %d pipe_id= %d\n", 571beb73b26SJeeja KP mconfig->pipe->state, mconfig->pipe->ppl_id); 572beb73b26SJeeja KP return -EIO; 573beb73b26SJeeja KP } 574beb73b26SJeeja KP 575beb73b26SJeeja KP ret = skl_set_module_format(ctx, mconfig, 576beb73b26SJeeja KP &module_config_size, ¶m_data); 577beb73b26SJeeja KP if (ret < 0) { 578beb73b26SJeeja KP dev_err(ctx->dev, "Failed to set module format ret=%d\n", ret); 579beb73b26SJeeja KP return ret; 580beb73b26SJeeja KP } 581beb73b26SJeeja KP 582beb73b26SJeeja KP msg.module_id = mconfig->id.module_id; 583beb73b26SJeeja KP msg.instance_id = mconfig->id.instance_id; 584beb73b26SJeeja KP msg.ppl_instance_id = mconfig->pipe->ppl_id; 585beb73b26SJeeja KP msg.param_data_size = module_config_size; 586beb73b26SJeeja KP msg.core_id = mconfig->core_id; 587beb73b26SJeeja KP 588beb73b26SJeeja KP ret = skl_ipc_init_instance(&ctx->ipc, &msg, param_data); 589beb73b26SJeeja KP if (ret < 0) { 590beb73b26SJeeja KP dev_err(ctx->dev, "Failed to init instance ret=%d\n", ret); 591beb73b26SJeeja KP kfree(param_data); 592beb73b26SJeeja KP return ret; 593beb73b26SJeeja KP } 594beb73b26SJeeja KP mconfig->m_state = SKL_MODULE_INIT_DONE; 595beb73b26SJeeja KP 596beb73b26SJeeja KP return ret; 597beb73b26SJeeja KP } 598beb73b26SJeeja KP 599beb73b26SJeeja KP static void skl_dump_bind_info(struct skl_sst *ctx, struct skl_module_cfg 600beb73b26SJeeja KP *src_module, struct skl_module_cfg *dst_module) 601beb73b26SJeeja KP { 602beb73b26SJeeja KP dev_dbg(ctx->dev, "%s: src module_id = %d src_instance=%d\n", 603beb73b26SJeeja KP __func__, src_module->id.module_id, src_module->id.instance_id); 604beb73b26SJeeja KP dev_dbg(ctx->dev, "%s: dst_module=%d dst_instacne=%d\n", __func__, 605beb73b26SJeeja KP dst_module->id.module_id, dst_module->id.instance_id); 606beb73b26SJeeja KP 607beb73b26SJeeja KP dev_dbg(ctx->dev, "src_module state = %d dst module state = %d\n", 608beb73b26SJeeja KP src_module->m_state, dst_module->m_state); 609beb73b26SJeeja KP } 610beb73b26SJeeja KP 611beb73b26SJeeja KP /* 612beb73b26SJeeja KP * On module freeup, we need to unbind the module with modules 613beb73b26SJeeja KP * it is already bind. 614beb73b26SJeeja KP * Find the pin allocated and unbind then using bind_unbind IPC 615beb73b26SJeeja KP */ 616beb73b26SJeeja KP int skl_unbind_modules(struct skl_sst *ctx, 617beb73b26SJeeja KP struct skl_module_cfg *src_mcfg, 618beb73b26SJeeja KP struct skl_module_cfg *dst_mcfg) 619beb73b26SJeeja KP { 620beb73b26SJeeja KP int ret; 621beb73b26SJeeja KP struct skl_ipc_bind_unbind_msg msg; 622beb73b26SJeeja KP struct skl_module_inst_id src_id = src_mcfg->id; 623beb73b26SJeeja KP struct skl_module_inst_id dst_id = dst_mcfg->id; 624beb73b26SJeeja KP int in_max = dst_mcfg->max_in_queue; 625beb73b26SJeeja KP int out_max = src_mcfg->max_out_queue; 6264f745708SJeeja KP int src_index, dst_index, src_pin_state, dst_pin_state; 627beb73b26SJeeja KP 628beb73b26SJeeja KP skl_dump_bind_info(ctx, src_mcfg, dst_mcfg); 629beb73b26SJeeja KP 630beb73b26SJeeja KP /* get src queue index */ 631beb73b26SJeeja KP src_index = skl_get_queue_index(src_mcfg->m_out_pin, dst_id, out_max); 632beb73b26SJeeja KP if (src_index < 0) 633beb73b26SJeeja KP return -EINVAL; 634beb73b26SJeeja KP 6354f745708SJeeja KP msg.src_queue = src_index; 636beb73b26SJeeja KP 637beb73b26SJeeja KP /* get dst queue index */ 638beb73b26SJeeja KP dst_index = skl_get_queue_index(dst_mcfg->m_in_pin, src_id, in_max); 639beb73b26SJeeja KP if (dst_index < 0) 640beb73b26SJeeja KP return -EINVAL; 641beb73b26SJeeja KP 6424f745708SJeeja KP msg.dst_queue = dst_index; 6434f745708SJeeja KP 6444f745708SJeeja KP src_pin_state = src_mcfg->m_out_pin[src_index].pin_state; 6454f745708SJeeja KP dst_pin_state = dst_mcfg->m_in_pin[dst_index].pin_state; 6464f745708SJeeja KP 6474f745708SJeeja KP if (src_pin_state != SKL_PIN_BIND_DONE || 6484f745708SJeeja KP dst_pin_state != SKL_PIN_BIND_DONE) 6494f745708SJeeja KP return 0; 650beb73b26SJeeja KP 651beb73b26SJeeja KP msg.module_id = src_mcfg->id.module_id; 652beb73b26SJeeja KP msg.instance_id = src_mcfg->id.instance_id; 653beb73b26SJeeja KP msg.dst_module_id = dst_mcfg->id.module_id; 654beb73b26SJeeja KP msg.dst_instance_id = dst_mcfg->id.instance_id; 655beb73b26SJeeja KP msg.bind = false; 656beb73b26SJeeja KP 657beb73b26SJeeja KP ret = skl_ipc_bind_unbind(&ctx->ipc, &msg); 658beb73b26SJeeja KP if (!ret) { 659beb73b26SJeeja KP /* free queue only if unbind is success */ 660beb73b26SJeeja KP skl_free_queue(src_mcfg->m_out_pin, src_index); 661beb73b26SJeeja KP skl_free_queue(dst_mcfg->m_in_pin, dst_index); 6624f745708SJeeja KP 6634f745708SJeeja KP /* 6644f745708SJeeja KP * check only if src module bind state, bind is 6654f745708SJeeja KP * always from src -> sink 6664f745708SJeeja KP */ 6674f745708SJeeja KP skl_clear_module_state(src_mcfg->m_out_pin, out_max, src_mcfg); 668beb73b26SJeeja KP } 669beb73b26SJeeja KP 670beb73b26SJeeja KP return ret; 671beb73b26SJeeja KP } 672beb73b26SJeeja KP 673beb73b26SJeeja KP /* 674beb73b26SJeeja KP * Once a module is instantiated it need to be 'bind' with other modules in 675beb73b26SJeeja KP * the pipeline. For binding we need to find the module pins which are bind 676beb73b26SJeeja KP * together 677beb73b26SJeeja KP * This function finds the pins and then sends bund_unbind IPC message to 678beb73b26SJeeja KP * DSP using IPC helper 679beb73b26SJeeja KP */ 680beb73b26SJeeja KP int skl_bind_modules(struct skl_sst *ctx, 681beb73b26SJeeja KP struct skl_module_cfg *src_mcfg, 682beb73b26SJeeja KP struct skl_module_cfg *dst_mcfg) 683beb73b26SJeeja KP { 684beb73b26SJeeja KP int ret; 685beb73b26SJeeja KP struct skl_ipc_bind_unbind_msg msg; 686beb73b26SJeeja KP int in_max = dst_mcfg->max_in_queue; 687beb73b26SJeeja KP int out_max = src_mcfg->max_out_queue; 688beb73b26SJeeja KP int src_index, dst_index; 689beb73b26SJeeja KP 690beb73b26SJeeja KP skl_dump_bind_info(ctx, src_mcfg, dst_mcfg); 691beb73b26SJeeja KP 692beb73b26SJeeja KP if (src_mcfg->m_state < SKL_MODULE_INIT_DONE && 693beb73b26SJeeja KP dst_mcfg->m_state < SKL_MODULE_INIT_DONE) 694beb73b26SJeeja KP return 0; 695beb73b26SJeeja KP 6964f745708SJeeja KP src_index = skl_alloc_queue(src_mcfg->m_out_pin, dst_mcfg, out_max); 697beb73b26SJeeja KP if (src_index < 0) 698beb73b26SJeeja KP return -EINVAL; 699beb73b26SJeeja KP 7004f745708SJeeja KP msg.src_queue = src_index; 7014f745708SJeeja KP dst_index = skl_alloc_queue(dst_mcfg->m_in_pin, src_mcfg, in_max); 702beb73b26SJeeja KP if (dst_index < 0) { 703beb73b26SJeeja KP skl_free_queue(src_mcfg->m_out_pin, src_index); 704beb73b26SJeeja KP return -EINVAL; 705beb73b26SJeeja KP } 706beb73b26SJeeja KP 7074f745708SJeeja KP msg.dst_queue = dst_index; 708beb73b26SJeeja KP 709beb73b26SJeeja KP dev_dbg(ctx->dev, "src queue = %d dst queue =%d\n", 710beb73b26SJeeja KP msg.src_queue, msg.dst_queue); 711beb73b26SJeeja KP 712beb73b26SJeeja KP msg.module_id = src_mcfg->id.module_id; 713beb73b26SJeeja KP msg.instance_id = src_mcfg->id.instance_id; 714beb73b26SJeeja KP msg.dst_module_id = dst_mcfg->id.module_id; 715beb73b26SJeeja KP msg.dst_instance_id = dst_mcfg->id.instance_id; 716beb73b26SJeeja KP msg.bind = true; 717beb73b26SJeeja KP 718beb73b26SJeeja KP ret = skl_ipc_bind_unbind(&ctx->ipc, &msg); 719beb73b26SJeeja KP 720beb73b26SJeeja KP if (!ret) { 721beb73b26SJeeja KP src_mcfg->m_state = SKL_MODULE_BIND_DONE; 7224f745708SJeeja KP src_mcfg->m_out_pin[src_index].pin_state = SKL_PIN_BIND_DONE; 7234f745708SJeeja KP dst_mcfg->m_in_pin[dst_index].pin_state = SKL_PIN_BIND_DONE; 724beb73b26SJeeja KP } else { 725beb73b26SJeeja KP /* error case , if IPC fails, clear the queue index */ 726beb73b26SJeeja KP skl_free_queue(src_mcfg->m_out_pin, src_index); 727beb73b26SJeeja KP skl_free_queue(dst_mcfg->m_in_pin, dst_index); 728beb73b26SJeeja KP } 729beb73b26SJeeja KP 730beb73b26SJeeja KP return ret; 731beb73b26SJeeja KP } 732c9b1e834SJeeja KP 733c9b1e834SJeeja KP static int skl_set_pipe_state(struct skl_sst *ctx, struct skl_pipe *pipe, 734c9b1e834SJeeja KP enum skl_ipc_pipeline_state state) 735c9b1e834SJeeja KP { 736c9b1e834SJeeja KP dev_dbg(ctx->dev, "%s: pipe_satate = %d\n", __func__, state); 737c9b1e834SJeeja KP 738c9b1e834SJeeja KP return skl_ipc_set_pipeline_state(&ctx->ipc, pipe->ppl_id, state); 739c9b1e834SJeeja KP } 740c9b1e834SJeeja KP 741c9b1e834SJeeja KP /* 742c9b1e834SJeeja KP * A pipeline is a collection of modules. Before a module in instantiated a 743c9b1e834SJeeja KP * pipeline needs to be created for it. 744c9b1e834SJeeja KP * This function creates pipeline, by sending create pipeline IPC messages 745c9b1e834SJeeja KP * to FW 746c9b1e834SJeeja KP */ 747c9b1e834SJeeja KP int skl_create_pipeline(struct skl_sst *ctx, struct skl_pipe *pipe) 748c9b1e834SJeeja KP { 749c9b1e834SJeeja KP int ret; 750c9b1e834SJeeja KP 751c9b1e834SJeeja KP dev_dbg(ctx->dev, "%s: pipe_id = %d\n", __func__, pipe->ppl_id); 752c9b1e834SJeeja KP 753c9b1e834SJeeja KP ret = skl_ipc_create_pipeline(&ctx->ipc, pipe->memory_pages, 754c9b1e834SJeeja KP pipe->pipe_priority, pipe->ppl_id); 755c9b1e834SJeeja KP if (ret < 0) { 756c9b1e834SJeeja KP dev_err(ctx->dev, "Failed to create pipeline\n"); 757c9b1e834SJeeja KP return ret; 758c9b1e834SJeeja KP } 759c9b1e834SJeeja KP 760c9b1e834SJeeja KP pipe->state = SKL_PIPE_CREATED; 761c9b1e834SJeeja KP 762c9b1e834SJeeja KP return 0; 763c9b1e834SJeeja KP } 764c9b1e834SJeeja KP 765c9b1e834SJeeja KP /* 766c9b1e834SJeeja KP * A pipeline needs to be deleted on cleanup. If a pipeline is running, then 767c9b1e834SJeeja KP * pause the pipeline first and then delete it 768c9b1e834SJeeja KP * The pipe delete is done by sending delete pipeline IPC. DSP will stop the 769c9b1e834SJeeja KP * DMA engines and releases resources 770c9b1e834SJeeja KP */ 771c9b1e834SJeeja KP int skl_delete_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) 772c9b1e834SJeeja KP { 773c9b1e834SJeeja KP int ret; 774c9b1e834SJeeja KP 775c9b1e834SJeeja KP dev_dbg(ctx->dev, "%s: pipe = %d\n", __func__, pipe->ppl_id); 776c9b1e834SJeeja KP 777c9b1e834SJeeja KP /* If pipe is not started, do not try to stop the pipe in FW. */ 778c9b1e834SJeeja KP if (pipe->state > SKL_PIPE_STARTED) { 779c9b1e834SJeeja KP ret = skl_set_pipe_state(ctx, pipe, PPL_PAUSED); 780c9b1e834SJeeja KP if (ret < 0) { 781c9b1e834SJeeja KP dev_err(ctx->dev, "Failed to stop pipeline\n"); 782c9b1e834SJeeja KP return ret; 783c9b1e834SJeeja KP } 784c9b1e834SJeeja KP 785c9b1e834SJeeja KP pipe->state = SKL_PIPE_PAUSED; 786c9b1e834SJeeja KP } else { 787c9b1e834SJeeja KP /* If pipe was not created in FW, do not try to delete it */ 788c9b1e834SJeeja KP if (pipe->state < SKL_PIPE_CREATED) 789c9b1e834SJeeja KP return 0; 790c9b1e834SJeeja KP 791c9b1e834SJeeja KP ret = skl_ipc_delete_pipeline(&ctx->ipc, pipe->ppl_id); 792c9b1e834SJeeja KP if (ret < 0) 793c9b1e834SJeeja KP dev_err(ctx->dev, "Failed to delete pipeline\n"); 794c9b1e834SJeeja KP } 795c9b1e834SJeeja KP 796c9b1e834SJeeja KP return ret; 797c9b1e834SJeeja KP } 798c9b1e834SJeeja KP 799c9b1e834SJeeja KP /* 800c9b1e834SJeeja KP * A pipeline is also a scheduling entity in DSP which can be run, stopped 801c9b1e834SJeeja KP * For processing data the pipe need to be run by sending IPC set pipe state 802c9b1e834SJeeja KP * to DSP 803c9b1e834SJeeja KP */ 804c9b1e834SJeeja KP int skl_run_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) 805c9b1e834SJeeja KP { 806c9b1e834SJeeja KP int ret; 807c9b1e834SJeeja KP 808c9b1e834SJeeja KP dev_dbg(ctx->dev, "%s: pipe = %d\n", __func__, pipe->ppl_id); 809c9b1e834SJeeja KP 810c9b1e834SJeeja KP /* If pipe was not created in FW, do not try to pause or delete */ 811c9b1e834SJeeja KP if (pipe->state < SKL_PIPE_CREATED) 812c9b1e834SJeeja KP return 0; 813c9b1e834SJeeja KP 814c9b1e834SJeeja KP /* Pipe has to be paused before it is started */ 815c9b1e834SJeeja KP ret = skl_set_pipe_state(ctx, pipe, PPL_PAUSED); 816c9b1e834SJeeja KP if (ret < 0) { 817c9b1e834SJeeja KP dev_err(ctx->dev, "Failed to pause pipe\n"); 818c9b1e834SJeeja KP return ret; 819c9b1e834SJeeja KP } 820c9b1e834SJeeja KP 821c9b1e834SJeeja KP pipe->state = SKL_PIPE_PAUSED; 822c9b1e834SJeeja KP 823c9b1e834SJeeja KP ret = skl_set_pipe_state(ctx, pipe, PPL_RUNNING); 824c9b1e834SJeeja KP if (ret < 0) { 825c9b1e834SJeeja KP dev_err(ctx->dev, "Failed to start pipe\n"); 826c9b1e834SJeeja KP return ret; 827c9b1e834SJeeja KP } 828c9b1e834SJeeja KP 829c9b1e834SJeeja KP pipe->state = SKL_PIPE_STARTED; 830c9b1e834SJeeja KP 831c9b1e834SJeeja KP return 0; 832c9b1e834SJeeja KP } 833c9b1e834SJeeja KP 834c9b1e834SJeeja KP /* 835c9b1e834SJeeja KP * Stop the pipeline by sending set pipe state IPC 836c9b1e834SJeeja KP * DSP doesnt implement stop so we always send pause message 837c9b1e834SJeeja KP */ 838c9b1e834SJeeja KP int skl_stop_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) 839c9b1e834SJeeja KP { 840c9b1e834SJeeja KP int ret; 841c9b1e834SJeeja KP 842c9b1e834SJeeja KP dev_dbg(ctx->dev, "In %s pipe=%d\n", __func__, pipe->ppl_id); 843c9b1e834SJeeja KP 844c9b1e834SJeeja KP /* If pipe was not created in FW, do not try to pause or delete */ 845c9b1e834SJeeja KP if (pipe->state < SKL_PIPE_PAUSED) 846c9b1e834SJeeja KP return 0; 847c9b1e834SJeeja KP 848c9b1e834SJeeja KP ret = skl_set_pipe_state(ctx, pipe, PPL_PAUSED); 849c9b1e834SJeeja KP if (ret < 0) { 850c9b1e834SJeeja KP dev_dbg(ctx->dev, "Failed to stop pipe\n"); 851c9b1e834SJeeja KP return ret; 852c9b1e834SJeeja KP } 853c9b1e834SJeeja KP 854c9b1e834SJeeja KP pipe->state = SKL_PIPE_CREATED; 855c9b1e834SJeeja KP 856c9b1e834SJeeja KP return 0; 857c9b1e834SJeeja KP } 858