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 57d255b095SJeeja KP int skl_init_dsp(struct skl *skl) 58d255b095SJeeja KP { 59d255b095SJeeja KP void __iomem *mmio_base; 60d255b095SJeeja KP struct hdac_ext_bus *ebus = &skl->ebus; 61d255b095SJeeja KP struct hdac_bus *bus = ebus_to_hbus(ebus); 62d255b095SJeeja KP int irq = bus->irq; 63d255b095SJeeja KP struct skl_dsp_loader_ops loader_ops; 64d255b095SJeeja KP int ret; 65d255b095SJeeja KP 66d255b095SJeeja KP loader_ops.alloc_dma_buf = skl_alloc_dma_buf; 67d255b095SJeeja KP loader_ops.free_dma_buf = skl_free_dma_buf; 68d255b095SJeeja KP 69d255b095SJeeja KP /* enable ppcap interrupt */ 70d255b095SJeeja KP snd_hdac_ext_bus_ppcap_enable(&skl->ebus, true); 71d255b095SJeeja KP snd_hdac_ext_bus_ppcap_int_enable(&skl->ebus, true); 72d255b095SJeeja KP 73d255b095SJeeja KP /* read the BAR of the ADSP MMIO */ 74d255b095SJeeja KP mmio_base = pci_ioremap_bar(skl->pci, 4); 75d255b095SJeeja KP if (mmio_base == NULL) { 76d255b095SJeeja KP dev_err(bus->dev, "ioremap error\n"); 77d255b095SJeeja KP return -ENXIO; 78d255b095SJeeja KP } 79d255b095SJeeja KP 80d255b095SJeeja KP ret = skl_sst_dsp_init(bus->dev, mmio_base, irq, 81d255b095SJeeja KP loader_ops, &skl->skl_sst); 82d255b095SJeeja KP 83d255b095SJeeja KP dev_dbg(bus->dev, "dsp registration status=%d\n", ret); 84d255b095SJeeja KP 85d255b095SJeeja KP return ret; 86d255b095SJeeja KP } 87d255b095SJeeja KP 88d255b095SJeeja KP void skl_free_dsp(struct skl *skl) 89d255b095SJeeja KP { 90d255b095SJeeja KP struct hdac_ext_bus *ebus = &skl->ebus; 91d255b095SJeeja KP struct hdac_bus *bus = ebus_to_hbus(ebus); 92d255b095SJeeja KP struct skl_sst *ctx = skl->skl_sst; 93d255b095SJeeja KP 94d255b095SJeeja KP /* disable ppcap interrupt */ 95d255b095SJeeja KP snd_hdac_ext_bus_ppcap_int_enable(&skl->ebus, false); 96d255b095SJeeja KP 97d255b095SJeeja KP skl_sst_dsp_cleanup(bus->dev, ctx); 98d255b095SJeeja KP if (ctx->dsp->addr.lpe) 99d255b095SJeeja KP iounmap(ctx->dsp->addr.lpe); 100d255b095SJeeja KP } 101d255b095SJeeja KP 102d255b095SJeeja KP int skl_suspend_dsp(struct skl *skl) 103d255b095SJeeja KP { 104d255b095SJeeja KP struct skl_sst *ctx = skl->skl_sst; 105d255b095SJeeja KP int ret; 106d255b095SJeeja KP 107d255b095SJeeja KP /* if ppcap is not supported return 0 */ 108d255b095SJeeja KP if (!skl->ebus.ppcap) 109d255b095SJeeja KP return 0; 110d255b095SJeeja KP 111d255b095SJeeja KP ret = skl_dsp_sleep(ctx->dsp); 112d255b095SJeeja KP if (ret < 0) 113d255b095SJeeja KP return ret; 114d255b095SJeeja KP 115d255b095SJeeja KP /* disable ppcap interrupt */ 116d255b095SJeeja KP snd_hdac_ext_bus_ppcap_int_enable(&skl->ebus, false); 117d255b095SJeeja KP snd_hdac_ext_bus_ppcap_enable(&skl->ebus, false); 118d255b095SJeeja KP 119d255b095SJeeja KP return 0; 120d255b095SJeeja KP } 121d255b095SJeeja KP 122d255b095SJeeja KP int skl_resume_dsp(struct skl *skl) 123d255b095SJeeja KP { 124d255b095SJeeja KP struct skl_sst *ctx = skl->skl_sst; 125d255b095SJeeja KP 126d255b095SJeeja KP /* if ppcap is not supported return 0 */ 127d255b095SJeeja KP if (!skl->ebus.ppcap) 128d255b095SJeeja KP return 0; 129d255b095SJeeja KP 130d255b095SJeeja KP /* enable ppcap interrupt */ 131d255b095SJeeja KP snd_hdac_ext_bus_ppcap_enable(&skl->ebus, true); 132d255b095SJeeja KP snd_hdac_ext_bus_ppcap_int_enable(&skl->ebus, true); 133d255b095SJeeja KP 134d255b095SJeeja KP return skl_dsp_wake(ctx->dsp); 135d255b095SJeeja KP } 13623db472bSJeeja KP 13723db472bSJeeja KP enum skl_bitdepth skl_get_bit_depth(int params) 13823db472bSJeeja KP { 13923db472bSJeeja KP switch (params) { 14023db472bSJeeja KP case 8: 14123db472bSJeeja KP return SKL_DEPTH_8BIT; 14223db472bSJeeja KP 14323db472bSJeeja KP case 16: 14423db472bSJeeja KP return SKL_DEPTH_16BIT; 14523db472bSJeeja KP 14623db472bSJeeja KP case 24: 14723db472bSJeeja KP return SKL_DEPTH_24BIT; 14823db472bSJeeja KP 14923db472bSJeeja KP case 32: 15023db472bSJeeja KP return SKL_DEPTH_32BIT; 15123db472bSJeeja KP 15223db472bSJeeja KP default: 15323db472bSJeeja KP return SKL_DEPTH_INVALID; 15423db472bSJeeja KP 15523db472bSJeeja KP } 15623db472bSJeeja KP } 15723db472bSJeeja KP 15823db472bSJeeja KP static u32 skl_create_channel_map(enum skl_ch_cfg ch_cfg) 15923db472bSJeeja KP { 16023db472bSJeeja KP u32 config; 16123db472bSJeeja KP 16223db472bSJeeja KP switch (ch_cfg) { 16323db472bSJeeja KP case SKL_CH_CFG_MONO: 16423db472bSJeeja KP config = (0xFFFFFFF0 | SKL_CHANNEL_LEFT); 16523db472bSJeeja KP break; 16623db472bSJeeja KP 16723db472bSJeeja KP case SKL_CH_CFG_STEREO: 16823db472bSJeeja KP config = (0xFFFFFF00 | SKL_CHANNEL_LEFT 16923db472bSJeeja KP | (SKL_CHANNEL_RIGHT << 4)); 17023db472bSJeeja KP break; 17123db472bSJeeja KP 17223db472bSJeeja KP case SKL_CH_CFG_2_1: 17323db472bSJeeja KP config = (0xFFFFF000 | SKL_CHANNEL_LEFT 17423db472bSJeeja KP | (SKL_CHANNEL_RIGHT << 4) 17523db472bSJeeja KP | (SKL_CHANNEL_LFE << 8)); 17623db472bSJeeja KP break; 17723db472bSJeeja KP 17823db472bSJeeja KP case SKL_CH_CFG_3_0: 17923db472bSJeeja KP config = (0xFFFFF000 | SKL_CHANNEL_LEFT 18023db472bSJeeja KP | (SKL_CHANNEL_CENTER << 4) 18123db472bSJeeja KP | (SKL_CHANNEL_RIGHT << 8)); 18223db472bSJeeja KP break; 18323db472bSJeeja KP 18423db472bSJeeja KP case SKL_CH_CFG_3_1: 18523db472bSJeeja KP config = (0xFFFF0000 | SKL_CHANNEL_LEFT 18623db472bSJeeja KP | (SKL_CHANNEL_CENTER << 4) 18723db472bSJeeja KP | (SKL_CHANNEL_RIGHT << 8) 18823db472bSJeeja KP | (SKL_CHANNEL_LFE << 12)); 18923db472bSJeeja KP break; 19023db472bSJeeja KP 19123db472bSJeeja KP case SKL_CH_CFG_QUATRO: 19223db472bSJeeja KP config = (0xFFFF0000 | SKL_CHANNEL_LEFT 19323db472bSJeeja KP | (SKL_CHANNEL_RIGHT << 4) 19423db472bSJeeja KP | (SKL_CHANNEL_LEFT_SURROUND << 8) 19523db472bSJeeja KP | (SKL_CHANNEL_RIGHT_SURROUND << 12)); 19623db472bSJeeja KP break; 19723db472bSJeeja KP 19823db472bSJeeja KP case SKL_CH_CFG_4_0: 19923db472bSJeeja KP config = (0xFFFF0000 | SKL_CHANNEL_LEFT 20023db472bSJeeja KP | (SKL_CHANNEL_CENTER << 4) 20123db472bSJeeja KP | (SKL_CHANNEL_RIGHT << 8) 20223db472bSJeeja KP | (SKL_CHANNEL_CENTER_SURROUND << 12)); 20323db472bSJeeja KP break; 20423db472bSJeeja KP 20523db472bSJeeja KP case SKL_CH_CFG_5_0: 20623db472bSJeeja KP config = (0xFFF00000 | SKL_CHANNEL_LEFT 20723db472bSJeeja KP | (SKL_CHANNEL_CENTER << 4) 20823db472bSJeeja KP | (SKL_CHANNEL_RIGHT << 8) 20923db472bSJeeja KP | (SKL_CHANNEL_LEFT_SURROUND << 12) 21023db472bSJeeja KP | (SKL_CHANNEL_RIGHT_SURROUND << 16)); 21123db472bSJeeja KP break; 21223db472bSJeeja KP 21323db472bSJeeja KP case SKL_CH_CFG_5_1: 21423db472bSJeeja KP config = (0xFF000000 | SKL_CHANNEL_CENTER 21523db472bSJeeja KP | (SKL_CHANNEL_LEFT << 4) 21623db472bSJeeja KP | (SKL_CHANNEL_RIGHT << 8) 21723db472bSJeeja KP | (SKL_CHANNEL_LEFT_SURROUND << 12) 21823db472bSJeeja KP | (SKL_CHANNEL_RIGHT_SURROUND << 16) 21923db472bSJeeja KP | (SKL_CHANNEL_LFE << 20)); 22023db472bSJeeja KP break; 22123db472bSJeeja KP 22223db472bSJeeja KP case SKL_CH_CFG_DUAL_MONO: 22323db472bSJeeja KP config = (0xFFFFFF00 | SKL_CHANNEL_LEFT 22423db472bSJeeja KP | (SKL_CHANNEL_LEFT << 4)); 22523db472bSJeeja KP break; 22623db472bSJeeja KP 22723db472bSJeeja KP case SKL_CH_CFG_I2S_DUAL_STEREO_0: 22823db472bSJeeja KP config = (0xFFFFFF00 | SKL_CHANNEL_LEFT 22923db472bSJeeja KP | (SKL_CHANNEL_RIGHT << 4)); 23023db472bSJeeja KP break; 23123db472bSJeeja KP 23223db472bSJeeja KP case SKL_CH_CFG_I2S_DUAL_STEREO_1: 23323db472bSJeeja KP config = (0xFFFF00FF | (SKL_CHANNEL_LEFT << 8) 23423db472bSJeeja KP | (SKL_CHANNEL_RIGHT << 12)); 23523db472bSJeeja KP break; 23623db472bSJeeja KP 23723db472bSJeeja KP default: 23823db472bSJeeja KP config = 0xFFFFFFFF; 23923db472bSJeeja KP break; 24023db472bSJeeja KP 24123db472bSJeeja KP } 24223db472bSJeeja KP 24323db472bSJeeja KP return config; 24423db472bSJeeja KP } 24523db472bSJeeja KP 24623db472bSJeeja KP /* 24723db472bSJeeja KP * Each module in DSP expects a base module configuration, which consists of 24823db472bSJeeja KP * PCM format information, which we calculate in driver and resource values 24923db472bSJeeja KP * which are read from widget information passed through topology binary 25023db472bSJeeja KP * This is send when we create a module with INIT_INSTANCE IPC msg 25123db472bSJeeja KP */ 25223db472bSJeeja KP static void skl_set_base_module_format(struct skl_sst *ctx, 25323db472bSJeeja KP struct skl_module_cfg *mconfig, 25423db472bSJeeja KP struct skl_base_cfg *base_cfg) 25523db472bSJeeja KP { 25623db472bSJeeja KP struct skl_module_fmt *format = &mconfig->in_fmt; 25723db472bSJeeja KP 25823db472bSJeeja KP base_cfg->audio_fmt.number_of_channels = (u8)format->channels; 25923db472bSJeeja KP 26023db472bSJeeja KP base_cfg->audio_fmt.s_freq = format->s_freq; 26123db472bSJeeja KP base_cfg->audio_fmt.bit_depth = format->bit_depth; 26223db472bSJeeja KP base_cfg->audio_fmt.valid_bit_depth = format->valid_bit_depth; 26323db472bSJeeja KP base_cfg->audio_fmt.ch_cfg = format->ch_cfg; 26423db472bSJeeja KP 26523db472bSJeeja KP dev_dbg(ctx->dev, "bit_depth=%x valid_bd=%x ch_config=%x\n", 26623db472bSJeeja KP format->bit_depth, format->valid_bit_depth, 26723db472bSJeeja KP format->ch_cfg); 26823db472bSJeeja KP 26923db472bSJeeja KP base_cfg->audio_fmt.channel_map = skl_create_channel_map( 27023db472bSJeeja KP base_cfg->audio_fmt.ch_cfg); 27123db472bSJeeja KP 27223db472bSJeeja KP base_cfg->audio_fmt.interleaving = SKL_INTERLEAVING_PER_CHANNEL; 27323db472bSJeeja KP 27423db472bSJeeja KP base_cfg->cps = mconfig->mcps; 27523db472bSJeeja KP base_cfg->ibs = mconfig->ibs; 27623db472bSJeeja KP base_cfg->obs = mconfig->obs; 27723db472bSJeeja KP } 27823db472bSJeeja KP 27923db472bSJeeja KP /* 28023db472bSJeeja KP * Copies copier capabilities into copier module and updates copier module 28123db472bSJeeja KP * config size. 28223db472bSJeeja KP */ 28323db472bSJeeja KP static void skl_copy_copier_caps(struct skl_module_cfg *mconfig, 28423db472bSJeeja KP struct skl_cpr_cfg *cpr_mconfig) 28523db472bSJeeja KP { 28623db472bSJeeja KP if (mconfig->formats_config.caps_size == 0) 28723db472bSJeeja KP return; 28823db472bSJeeja KP 28923db472bSJeeja KP memcpy(cpr_mconfig->gtw_cfg.config_data, 29023db472bSJeeja KP mconfig->formats_config.caps, 29123db472bSJeeja KP mconfig->formats_config.caps_size); 29223db472bSJeeja KP 29323db472bSJeeja KP cpr_mconfig->gtw_cfg.config_length = 29423db472bSJeeja KP (mconfig->formats_config.caps_size) / 4; 29523db472bSJeeja KP } 29623db472bSJeeja KP 29723db472bSJeeja KP /* 29823db472bSJeeja KP * Calculate the gatewat settings required for copier module, type of 29923db472bSJeeja KP * gateway and index of gateway to use 30023db472bSJeeja KP */ 30123db472bSJeeja KP static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx, 30223db472bSJeeja KP struct skl_module_cfg *mconfig, 30323db472bSJeeja KP struct skl_cpr_cfg *cpr_mconfig) 30423db472bSJeeja KP { 30523db472bSJeeja KP union skl_connector_node_id node_id = {0}; 306d7b18813SJeeja KP union skl_ssp_dma_node ssp_node = {0}; 30723db472bSJeeja KP struct skl_pipe_params *params = mconfig->pipe->p_params; 30823db472bSJeeja KP 30923db472bSJeeja KP switch (mconfig->dev_type) { 31023db472bSJeeja KP case SKL_DEVICE_BT: 31123db472bSJeeja KP node_id.node.dma_type = 31223db472bSJeeja KP (SKL_CONN_SOURCE == mconfig->hw_conn_type) ? 31323db472bSJeeja KP SKL_DMA_I2S_LINK_OUTPUT_CLASS : 31423db472bSJeeja KP SKL_DMA_I2S_LINK_INPUT_CLASS; 31523db472bSJeeja KP node_id.node.vindex = params->host_dma_id + 31623db472bSJeeja KP (mconfig->vbus_id << 3); 31723db472bSJeeja KP break; 31823db472bSJeeja KP 31923db472bSJeeja KP case SKL_DEVICE_I2S: 32023db472bSJeeja KP node_id.node.dma_type = 32123db472bSJeeja KP (SKL_CONN_SOURCE == mconfig->hw_conn_type) ? 32223db472bSJeeja KP SKL_DMA_I2S_LINK_OUTPUT_CLASS : 32323db472bSJeeja KP SKL_DMA_I2S_LINK_INPUT_CLASS; 324d7b18813SJeeja KP ssp_node.dma_node.time_slot_index = mconfig->time_slot; 325d7b18813SJeeja KP ssp_node.dma_node.i2s_instance = mconfig->vbus_id; 326d7b18813SJeeja KP node_id.node.vindex = ssp_node.val; 32723db472bSJeeja KP break; 32823db472bSJeeja KP 32923db472bSJeeja KP case SKL_DEVICE_DMIC: 33023db472bSJeeja KP node_id.node.dma_type = SKL_DMA_DMIC_LINK_INPUT_CLASS; 33123db472bSJeeja KP node_id.node.vindex = mconfig->vbus_id + 33223db472bSJeeja KP (mconfig->time_slot); 33323db472bSJeeja KP break; 33423db472bSJeeja KP 33523db472bSJeeja KP case SKL_DEVICE_HDALINK: 33623db472bSJeeja KP node_id.node.dma_type = 33723db472bSJeeja KP (SKL_CONN_SOURCE == mconfig->hw_conn_type) ? 33823db472bSJeeja KP SKL_DMA_HDA_LINK_OUTPUT_CLASS : 33923db472bSJeeja KP SKL_DMA_HDA_LINK_INPUT_CLASS; 34023db472bSJeeja KP node_id.node.vindex = params->link_dma_id; 34123db472bSJeeja KP break; 34223db472bSJeeja KP 34323db472bSJeeja KP default: 34423db472bSJeeja KP node_id.node.dma_type = 34523db472bSJeeja KP (SKL_CONN_SOURCE == mconfig->hw_conn_type) ? 34623db472bSJeeja KP SKL_DMA_HDA_HOST_OUTPUT_CLASS : 34723db472bSJeeja KP SKL_DMA_HDA_HOST_INPUT_CLASS; 34823db472bSJeeja KP node_id.node.vindex = params->host_dma_id; 34923db472bSJeeja KP break; 35023db472bSJeeja KP } 35123db472bSJeeja KP 35223db472bSJeeja KP cpr_mconfig->gtw_cfg.node_id = node_id.val; 35323db472bSJeeja KP 35423db472bSJeeja KP if (SKL_CONN_SOURCE == mconfig->hw_conn_type) 35523db472bSJeeja KP cpr_mconfig->gtw_cfg.dma_buffer_size = 2 * mconfig->obs; 35623db472bSJeeja KP else 35723db472bSJeeja KP cpr_mconfig->gtw_cfg.dma_buffer_size = 2 * mconfig->ibs; 35823db472bSJeeja KP 35923db472bSJeeja KP cpr_mconfig->cpr_feature_mask = 0; 36023db472bSJeeja KP cpr_mconfig->gtw_cfg.config_length = 0; 36123db472bSJeeja KP 36223db472bSJeeja KP skl_copy_copier_caps(mconfig, cpr_mconfig); 36323db472bSJeeja KP } 36423db472bSJeeja KP 36523db472bSJeeja KP static void skl_setup_out_format(struct skl_sst *ctx, 36623db472bSJeeja KP struct skl_module_cfg *mconfig, 36723db472bSJeeja KP struct skl_audio_data_format *out_fmt) 36823db472bSJeeja KP { 36923db472bSJeeja KP struct skl_module_fmt *format = &mconfig->out_fmt; 37023db472bSJeeja KP 37123db472bSJeeja KP out_fmt->number_of_channels = (u8)format->channels; 37223db472bSJeeja KP out_fmt->s_freq = format->s_freq; 37323db472bSJeeja KP out_fmt->bit_depth = format->bit_depth; 37423db472bSJeeja KP out_fmt->valid_bit_depth = format->valid_bit_depth; 37523db472bSJeeja KP out_fmt->ch_cfg = format->ch_cfg; 37623db472bSJeeja KP 37723db472bSJeeja KP out_fmt->channel_map = skl_create_channel_map(out_fmt->ch_cfg); 37823db472bSJeeja KP out_fmt->interleaving = SKL_INTERLEAVING_PER_CHANNEL; 37923db472bSJeeja KP 38023db472bSJeeja KP dev_dbg(ctx->dev, "copier out format chan=%d fre=%d bitdepth=%d\n", 38123db472bSJeeja KP out_fmt->number_of_channels, format->s_freq, format->bit_depth); 38223db472bSJeeja KP } 38323db472bSJeeja KP 38423db472bSJeeja KP /* 385a0ffe48bSHardik T Shah * DSP needs SRC module for frequency conversion, SRC takes base module 386a0ffe48bSHardik T Shah * configuration and the target frequency as extra parameter passed as src 387a0ffe48bSHardik T Shah * config 388a0ffe48bSHardik T Shah */ 389a0ffe48bSHardik T Shah static void skl_set_src_format(struct skl_sst *ctx, 390a0ffe48bSHardik T Shah struct skl_module_cfg *mconfig, 391a0ffe48bSHardik T Shah struct skl_src_module_cfg *src_mconfig) 392a0ffe48bSHardik T Shah { 393a0ffe48bSHardik T Shah struct skl_module_fmt *fmt = &mconfig->out_fmt; 394a0ffe48bSHardik T Shah 395a0ffe48bSHardik T Shah skl_set_base_module_format(ctx, mconfig, 396a0ffe48bSHardik T Shah (struct skl_base_cfg *)src_mconfig); 397a0ffe48bSHardik T Shah 398a0ffe48bSHardik T Shah src_mconfig->src_cfg = fmt->s_freq; 399a0ffe48bSHardik T Shah } 400a0ffe48bSHardik T Shah 401a0ffe48bSHardik T Shah /* 402a0ffe48bSHardik T Shah * DSP needs updown module to do channel conversion. updown module take base 403a0ffe48bSHardik T Shah * module configuration and channel configuration 404a0ffe48bSHardik T Shah * It also take coefficients and now we have defaults applied here 405a0ffe48bSHardik T Shah */ 406a0ffe48bSHardik T Shah static void skl_set_updown_mixer_format(struct skl_sst *ctx, 407a0ffe48bSHardik T Shah struct skl_module_cfg *mconfig, 408a0ffe48bSHardik T Shah struct skl_up_down_mixer_cfg *mixer_mconfig) 409a0ffe48bSHardik T Shah { 410a0ffe48bSHardik T Shah struct skl_module_fmt *fmt = &mconfig->out_fmt; 411a0ffe48bSHardik T Shah int i = 0; 412a0ffe48bSHardik T Shah 413a0ffe48bSHardik T Shah skl_set_base_module_format(ctx, mconfig, 414a0ffe48bSHardik T Shah (struct skl_base_cfg *)mixer_mconfig); 415a0ffe48bSHardik T Shah mixer_mconfig->out_ch_cfg = fmt->ch_cfg; 416a0ffe48bSHardik T Shah 417a0ffe48bSHardik T Shah /* Select F/W default coefficient */ 418a0ffe48bSHardik T Shah mixer_mconfig->coeff_sel = 0x0; 419a0ffe48bSHardik T Shah 420a0ffe48bSHardik T Shah /* User coeff, don't care since we are selecting F/W defaults */ 421a0ffe48bSHardik T Shah for (i = 0; i < UP_DOWN_MIXER_MAX_COEFF; i++) 422a0ffe48bSHardik T Shah mixer_mconfig->coeff[i] = 0xDEADBEEF; 423a0ffe48bSHardik T Shah } 424a0ffe48bSHardik T Shah 425a0ffe48bSHardik T Shah /* 42623db472bSJeeja KP * 'copier' is DSP internal module which copies data from Host DMA (HDA host 42723db472bSJeeja KP * dma) or link (hda link, SSP, PDM) 42823db472bSJeeja KP * Here we calculate the copier module parameters, like PCM format, output 42923db472bSJeeja KP * format, gateway settings 43023db472bSJeeja KP * copier_module_config is sent as input buffer with INIT_INSTANCE IPC msg 43123db472bSJeeja KP */ 43223db472bSJeeja KP static void skl_set_copier_format(struct skl_sst *ctx, 43323db472bSJeeja KP struct skl_module_cfg *mconfig, 43423db472bSJeeja KP struct skl_cpr_cfg *cpr_mconfig) 43523db472bSJeeja KP { 43623db472bSJeeja KP struct skl_audio_data_format *out_fmt = &cpr_mconfig->out_fmt; 43723db472bSJeeja KP struct skl_base_cfg *base_cfg = (struct skl_base_cfg *)cpr_mconfig; 43823db472bSJeeja KP 43923db472bSJeeja KP skl_set_base_module_format(ctx, mconfig, base_cfg); 44023db472bSJeeja KP 44123db472bSJeeja KP skl_setup_out_format(ctx, mconfig, out_fmt); 44223db472bSJeeja KP skl_setup_cpr_gateway_cfg(ctx, mconfig, cpr_mconfig); 44323db472bSJeeja KP } 44423db472bSJeeja KP 44523db472bSJeeja KP static u16 skl_get_module_param_size(struct skl_sst *ctx, 44623db472bSJeeja KP struct skl_module_cfg *mconfig) 44723db472bSJeeja KP { 44823db472bSJeeja KP u16 param_size; 44923db472bSJeeja KP 45023db472bSJeeja KP switch (mconfig->m_type) { 45123db472bSJeeja KP case SKL_MODULE_TYPE_COPIER: 45223db472bSJeeja KP param_size = sizeof(struct skl_cpr_cfg); 45323db472bSJeeja KP param_size += mconfig->formats_config.caps_size; 45423db472bSJeeja KP return param_size; 45523db472bSJeeja KP 456a0ffe48bSHardik T Shah case SKL_MODULE_TYPE_SRCINT: 457a0ffe48bSHardik T Shah return sizeof(struct skl_src_module_cfg); 458a0ffe48bSHardik T Shah 459a0ffe48bSHardik T Shah case SKL_MODULE_TYPE_UPDWMIX: 460a0ffe48bSHardik T Shah return sizeof(struct skl_up_down_mixer_cfg); 461a0ffe48bSHardik T Shah 46223db472bSJeeja KP default: 46323db472bSJeeja KP /* 46423db472bSJeeja KP * return only base cfg when no specific module type is 46523db472bSJeeja KP * specified 46623db472bSJeeja KP */ 46723db472bSJeeja KP return sizeof(struct skl_base_cfg); 46823db472bSJeeja KP } 46923db472bSJeeja KP 47023db472bSJeeja KP return 0; 47123db472bSJeeja KP } 47223db472bSJeeja KP 47323db472bSJeeja KP /* 474a0ffe48bSHardik T Shah * DSP firmware supports various modules like copier, SRC, updown etc. 475a0ffe48bSHardik T Shah * These modules required various parameters to be calculated and sent for 476a0ffe48bSHardik T Shah * the module initialization to DSP. By default a generic module needs only 477a0ffe48bSHardik T Shah * base module format configuration 47823db472bSJeeja KP */ 479a0ffe48bSHardik T Shah 48023db472bSJeeja KP static int skl_set_module_format(struct skl_sst *ctx, 48123db472bSJeeja KP struct skl_module_cfg *module_config, 48223db472bSJeeja KP u16 *module_config_size, 48323db472bSJeeja KP void **param_data) 48423db472bSJeeja KP { 48523db472bSJeeja KP u16 param_size; 48623db472bSJeeja KP 48723db472bSJeeja KP param_size = skl_get_module_param_size(ctx, module_config); 48823db472bSJeeja KP 48923db472bSJeeja KP *param_data = kzalloc(param_size, GFP_KERNEL); 49023db472bSJeeja KP if (NULL == *param_data) 49123db472bSJeeja KP return -ENOMEM; 49223db472bSJeeja KP 49323db472bSJeeja KP *module_config_size = param_size; 49423db472bSJeeja KP 49523db472bSJeeja KP switch (module_config->m_type) { 49623db472bSJeeja KP case SKL_MODULE_TYPE_COPIER: 49723db472bSJeeja KP skl_set_copier_format(ctx, module_config, *param_data); 49823db472bSJeeja KP break; 49923db472bSJeeja KP 500a0ffe48bSHardik T Shah case SKL_MODULE_TYPE_SRCINT: 501a0ffe48bSHardik T Shah skl_set_src_format(ctx, module_config, *param_data); 502a0ffe48bSHardik T Shah break; 503a0ffe48bSHardik T Shah 504a0ffe48bSHardik T Shah case SKL_MODULE_TYPE_UPDWMIX: 505a0ffe48bSHardik T Shah skl_set_updown_mixer_format(ctx, module_config, *param_data); 506a0ffe48bSHardik T Shah break; 507a0ffe48bSHardik T Shah 50823db472bSJeeja KP default: 50923db472bSJeeja KP skl_set_base_module_format(ctx, module_config, *param_data); 51023db472bSJeeja KP break; 51123db472bSJeeja KP 51223db472bSJeeja KP } 51323db472bSJeeja KP 51423db472bSJeeja KP dev_dbg(ctx->dev, "Module type=%d config size: %d bytes\n", 51523db472bSJeeja KP module_config->id.module_id, param_size); 51623db472bSJeeja KP print_hex_dump(KERN_DEBUG, "Module params:", DUMP_PREFIX_OFFSET, 8, 4, 51723db472bSJeeja KP *param_data, param_size, false); 51823db472bSJeeja KP return 0; 51923db472bSJeeja KP } 52023db472bSJeeja KP 52123db472bSJeeja KP static int skl_get_queue_index(struct skl_module_pin *mpin, 52223db472bSJeeja KP struct skl_module_inst_id id, int max) 52323db472bSJeeja KP { 52423db472bSJeeja KP int i; 52523db472bSJeeja KP 52623db472bSJeeja KP for (i = 0; i < max; i++) { 52723db472bSJeeja KP if (mpin[i].id.module_id == id.module_id && 52823db472bSJeeja KP mpin[i].id.instance_id == id.instance_id) 52923db472bSJeeja KP return i; 53023db472bSJeeja KP } 53123db472bSJeeja KP 53223db472bSJeeja KP return -EINVAL; 53323db472bSJeeja KP } 53423db472bSJeeja KP 53523db472bSJeeja KP /* 53623db472bSJeeja KP * Allocates queue for each module. 53723db472bSJeeja KP * if dynamic, the pin_index is allocated 0 to max_pin. 53823db472bSJeeja KP * In static, the pin_index is fixed based on module_id and instance id 53923db472bSJeeja KP */ 54023db472bSJeeja KP static int skl_alloc_queue(struct skl_module_pin *mpin, 54123db472bSJeeja KP struct skl_module_inst_id id, int max) 54223db472bSJeeja KP { 54323db472bSJeeja KP int i; 54423db472bSJeeja KP 54523db472bSJeeja KP /* 54623db472bSJeeja KP * if pin in dynamic, find first free pin 54723db472bSJeeja KP * otherwise find match module and instance id pin as topology will 54823db472bSJeeja KP * ensure a unique pin is assigned to this so no need to 54923db472bSJeeja KP * allocate/free 55023db472bSJeeja KP */ 55123db472bSJeeja KP for (i = 0; i < max; i++) { 55223db472bSJeeja KP if (mpin[i].is_dynamic) { 55323db472bSJeeja KP if (!mpin[i].in_use) { 55423db472bSJeeja KP mpin[i].in_use = true; 55523db472bSJeeja KP mpin[i].id.module_id = id.module_id; 55623db472bSJeeja KP mpin[i].id.instance_id = id.instance_id; 55723db472bSJeeja KP return i; 55823db472bSJeeja KP } 55923db472bSJeeja KP } else { 56023db472bSJeeja KP if (mpin[i].id.module_id == id.module_id && 56123db472bSJeeja KP mpin[i].id.instance_id == id.instance_id) 56223db472bSJeeja KP return i; 56323db472bSJeeja KP } 56423db472bSJeeja KP } 56523db472bSJeeja KP 56623db472bSJeeja KP return -EINVAL; 56723db472bSJeeja KP } 56823db472bSJeeja KP 56923db472bSJeeja KP static void skl_free_queue(struct skl_module_pin *mpin, int q_index) 57023db472bSJeeja KP { 57123db472bSJeeja KP if (mpin[q_index].is_dynamic) { 57223db472bSJeeja KP mpin[q_index].in_use = false; 57323db472bSJeeja KP mpin[q_index].id.module_id = 0; 57423db472bSJeeja KP mpin[q_index].id.instance_id = 0; 57523db472bSJeeja KP } 57623db472bSJeeja KP } 577beb73b26SJeeja KP 578beb73b26SJeeja KP /* 579beb73b26SJeeja KP * A module needs to be instanataited in DSP. A mdoule is present in a 580beb73b26SJeeja KP * collection of module referred as a PIPE. 581beb73b26SJeeja KP * We first calculate the module format, based on module type and then 582beb73b26SJeeja KP * invoke the DSP by sending IPC INIT_INSTANCE using ipc helper 583beb73b26SJeeja KP */ 584beb73b26SJeeja KP int skl_init_module(struct skl_sst *ctx, 585beb73b26SJeeja KP struct skl_module_cfg *mconfig, char *param) 586beb73b26SJeeja KP { 587beb73b26SJeeja KP u16 module_config_size = 0; 588beb73b26SJeeja KP void *param_data = NULL; 589beb73b26SJeeja KP int ret; 590beb73b26SJeeja KP struct skl_ipc_init_instance_msg msg; 591beb73b26SJeeja KP 592beb73b26SJeeja KP dev_dbg(ctx->dev, "%s: module_id = %d instance=%d\n", __func__, 593beb73b26SJeeja KP mconfig->id.module_id, mconfig->id.instance_id); 594beb73b26SJeeja KP 595beb73b26SJeeja KP if (mconfig->pipe->state != SKL_PIPE_CREATED) { 596beb73b26SJeeja KP dev_err(ctx->dev, "Pipe not created state= %d pipe_id= %d\n", 597beb73b26SJeeja KP mconfig->pipe->state, mconfig->pipe->ppl_id); 598beb73b26SJeeja KP return -EIO; 599beb73b26SJeeja KP } 600beb73b26SJeeja KP 601beb73b26SJeeja KP ret = skl_set_module_format(ctx, mconfig, 602beb73b26SJeeja KP &module_config_size, ¶m_data); 603beb73b26SJeeja KP if (ret < 0) { 604beb73b26SJeeja KP dev_err(ctx->dev, "Failed to set module format ret=%d\n", ret); 605beb73b26SJeeja KP return ret; 606beb73b26SJeeja KP } 607beb73b26SJeeja KP 608beb73b26SJeeja KP msg.module_id = mconfig->id.module_id; 609beb73b26SJeeja KP msg.instance_id = mconfig->id.instance_id; 610beb73b26SJeeja KP msg.ppl_instance_id = mconfig->pipe->ppl_id; 611beb73b26SJeeja KP msg.param_data_size = module_config_size; 612beb73b26SJeeja KP msg.core_id = mconfig->core_id; 613beb73b26SJeeja KP 614beb73b26SJeeja KP ret = skl_ipc_init_instance(&ctx->ipc, &msg, param_data); 615beb73b26SJeeja KP if (ret < 0) { 616beb73b26SJeeja KP dev_err(ctx->dev, "Failed to init instance ret=%d\n", ret); 617beb73b26SJeeja KP kfree(param_data); 618beb73b26SJeeja KP return ret; 619beb73b26SJeeja KP } 620beb73b26SJeeja KP mconfig->m_state = SKL_MODULE_INIT_DONE; 621beb73b26SJeeja KP 622beb73b26SJeeja KP return ret; 623beb73b26SJeeja KP } 624beb73b26SJeeja KP 625beb73b26SJeeja KP static void skl_dump_bind_info(struct skl_sst *ctx, struct skl_module_cfg 626beb73b26SJeeja KP *src_module, struct skl_module_cfg *dst_module) 627beb73b26SJeeja KP { 628beb73b26SJeeja KP dev_dbg(ctx->dev, "%s: src module_id = %d src_instance=%d\n", 629beb73b26SJeeja KP __func__, src_module->id.module_id, src_module->id.instance_id); 630beb73b26SJeeja KP dev_dbg(ctx->dev, "%s: dst_module=%d dst_instacne=%d\n", __func__, 631beb73b26SJeeja KP dst_module->id.module_id, dst_module->id.instance_id); 632beb73b26SJeeja KP 633beb73b26SJeeja KP dev_dbg(ctx->dev, "src_module state = %d dst module state = %d\n", 634beb73b26SJeeja KP src_module->m_state, dst_module->m_state); 635beb73b26SJeeja KP } 636beb73b26SJeeja KP 637beb73b26SJeeja KP /* 638beb73b26SJeeja KP * On module freeup, we need to unbind the module with modules 639beb73b26SJeeja KP * it is already bind. 640beb73b26SJeeja KP * Find the pin allocated and unbind then using bind_unbind IPC 641beb73b26SJeeja KP */ 642beb73b26SJeeja KP int skl_unbind_modules(struct skl_sst *ctx, 643beb73b26SJeeja KP struct skl_module_cfg *src_mcfg, 644beb73b26SJeeja KP struct skl_module_cfg *dst_mcfg) 645beb73b26SJeeja KP { 646beb73b26SJeeja KP int ret; 647beb73b26SJeeja KP struct skl_ipc_bind_unbind_msg msg; 648beb73b26SJeeja KP struct skl_module_inst_id src_id = src_mcfg->id; 649beb73b26SJeeja KP struct skl_module_inst_id dst_id = dst_mcfg->id; 650beb73b26SJeeja KP int in_max = dst_mcfg->max_in_queue; 651beb73b26SJeeja KP int out_max = src_mcfg->max_out_queue; 652beb73b26SJeeja KP int src_index, dst_index; 653beb73b26SJeeja KP 654beb73b26SJeeja KP skl_dump_bind_info(ctx, src_mcfg, dst_mcfg); 655beb73b26SJeeja KP 656beb73b26SJeeja KP if (src_mcfg->m_state != SKL_MODULE_BIND_DONE) 657beb73b26SJeeja KP return 0; 658beb73b26SJeeja KP 659beb73b26SJeeja KP /* 660beb73b26SJeeja KP * if intra module unbind, check if both modules are BIND, 661beb73b26SJeeja KP * then send unbind 662beb73b26SJeeja KP */ 663beb73b26SJeeja KP if ((src_mcfg->pipe->ppl_id != dst_mcfg->pipe->ppl_id) && 664beb73b26SJeeja KP dst_mcfg->m_state != SKL_MODULE_BIND_DONE) 665beb73b26SJeeja KP return 0; 666beb73b26SJeeja KP else if (src_mcfg->m_state < SKL_MODULE_INIT_DONE && 667beb73b26SJeeja KP dst_mcfg->m_state < SKL_MODULE_INIT_DONE) 668beb73b26SJeeja KP return 0; 669beb73b26SJeeja KP 670beb73b26SJeeja KP /* get src queue index */ 671beb73b26SJeeja KP src_index = skl_get_queue_index(src_mcfg->m_out_pin, dst_id, out_max); 672beb73b26SJeeja KP if (src_index < 0) 673beb73b26SJeeja KP return -EINVAL; 674beb73b26SJeeja KP 675beb73b26SJeeja KP msg.src_queue = src_mcfg->m_out_pin[src_index].pin_index; 676beb73b26SJeeja KP 677beb73b26SJeeja KP /* get dst queue index */ 678beb73b26SJeeja KP dst_index = skl_get_queue_index(dst_mcfg->m_in_pin, src_id, in_max); 679beb73b26SJeeja KP if (dst_index < 0) 680beb73b26SJeeja KP return -EINVAL; 681beb73b26SJeeja KP 682beb73b26SJeeja KP msg.dst_queue = dst_mcfg->m_in_pin[dst_index].pin_index; 683beb73b26SJeeja KP 684beb73b26SJeeja KP msg.module_id = src_mcfg->id.module_id; 685beb73b26SJeeja KP msg.instance_id = src_mcfg->id.instance_id; 686beb73b26SJeeja KP msg.dst_module_id = dst_mcfg->id.module_id; 687beb73b26SJeeja KP msg.dst_instance_id = dst_mcfg->id.instance_id; 688beb73b26SJeeja KP msg.bind = false; 689beb73b26SJeeja KP 690beb73b26SJeeja KP ret = skl_ipc_bind_unbind(&ctx->ipc, &msg); 691beb73b26SJeeja KP if (!ret) { 692beb73b26SJeeja KP src_mcfg->m_state = SKL_MODULE_UNINIT; 693beb73b26SJeeja KP /* free queue only if unbind is success */ 694beb73b26SJeeja KP skl_free_queue(src_mcfg->m_out_pin, src_index); 695beb73b26SJeeja KP skl_free_queue(dst_mcfg->m_in_pin, dst_index); 696beb73b26SJeeja KP } 697beb73b26SJeeja KP 698beb73b26SJeeja KP return ret; 699beb73b26SJeeja KP } 700beb73b26SJeeja KP 701beb73b26SJeeja KP /* 702beb73b26SJeeja KP * Once a module is instantiated it need to be 'bind' with other modules in 703beb73b26SJeeja KP * the pipeline. For binding we need to find the module pins which are bind 704beb73b26SJeeja KP * together 705beb73b26SJeeja KP * This function finds the pins and then sends bund_unbind IPC message to 706beb73b26SJeeja KP * DSP using IPC helper 707beb73b26SJeeja KP */ 708beb73b26SJeeja KP int skl_bind_modules(struct skl_sst *ctx, 709beb73b26SJeeja KP struct skl_module_cfg *src_mcfg, 710beb73b26SJeeja KP struct skl_module_cfg *dst_mcfg) 711beb73b26SJeeja KP { 712beb73b26SJeeja KP int ret; 713beb73b26SJeeja KP struct skl_ipc_bind_unbind_msg msg; 714beb73b26SJeeja KP struct skl_module_inst_id src_id = src_mcfg->id; 715beb73b26SJeeja KP struct skl_module_inst_id dst_id = dst_mcfg->id; 716beb73b26SJeeja KP int in_max = dst_mcfg->max_in_queue; 717beb73b26SJeeja KP int out_max = src_mcfg->max_out_queue; 718beb73b26SJeeja KP int src_index, dst_index; 719beb73b26SJeeja KP 720beb73b26SJeeja KP skl_dump_bind_info(ctx, src_mcfg, dst_mcfg); 721beb73b26SJeeja KP 722beb73b26SJeeja KP if (src_mcfg->m_state < SKL_MODULE_INIT_DONE && 723beb73b26SJeeja KP dst_mcfg->m_state < SKL_MODULE_INIT_DONE) 724beb73b26SJeeja KP return 0; 725beb73b26SJeeja KP 726beb73b26SJeeja KP src_index = skl_alloc_queue(src_mcfg->m_out_pin, dst_id, out_max); 727beb73b26SJeeja KP if (src_index < 0) 728beb73b26SJeeja KP return -EINVAL; 729beb73b26SJeeja KP 730beb73b26SJeeja KP msg.src_queue = src_mcfg->m_out_pin[src_index].pin_index; 731beb73b26SJeeja KP dst_index = skl_alloc_queue(dst_mcfg->m_in_pin, src_id, in_max); 732beb73b26SJeeja KP if (dst_index < 0) { 733beb73b26SJeeja KP skl_free_queue(src_mcfg->m_out_pin, src_index); 734beb73b26SJeeja KP return -EINVAL; 735beb73b26SJeeja KP } 736beb73b26SJeeja KP 737beb73b26SJeeja KP msg.dst_queue = dst_mcfg->m_in_pin[dst_index].pin_index; 738beb73b26SJeeja KP 739beb73b26SJeeja KP dev_dbg(ctx->dev, "src queue = %d dst queue =%d\n", 740beb73b26SJeeja KP msg.src_queue, msg.dst_queue); 741beb73b26SJeeja KP 742beb73b26SJeeja KP msg.module_id = src_mcfg->id.module_id; 743beb73b26SJeeja KP msg.instance_id = src_mcfg->id.instance_id; 744beb73b26SJeeja KP msg.dst_module_id = dst_mcfg->id.module_id; 745beb73b26SJeeja KP msg.dst_instance_id = dst_mcfg->id.instance_id; 746beb73b26SJeeja KP msg.bind = true; 747beb73b26SJeeja KP 748beb73b26SJeeja KP ret = skl_ipc_bind_unbind(&ctx->ipc, &msg); 749beb73b26SJeeja KP 750beb73b26SJeeja KP if (!ret) { 751beb73b26SJeeja KP src_mcfg->m_state = SKL_MODULE_BIND_DONE; 752beb73b26SJeeja KP } else { 753beb73b26SJeeja KP /* error case , if IPC fails, clear the queue index */ 754beb73b26SJeeja KP skl_free_queue(src_mcfg->m_out_pin, src_index); 755beb73b26SJeeja KP skl_free_queue(dst_mcfg->m_in_pin, dst_index); 756beb73b26SJeeja KP } 757beb73b26SJeeja KP 758beb73b26SJeeja KP return ret; 759beb73b26SJeeja KP } 760c9b1e834SJeeja KP 761c9b1e834SJeeja KP static int skl_set_pipe_state(struct skl_sst *ctx, struct skl_pipe *pipe, 762c9b1e834SJeeja KP enum skl_ipc_pipeline_state state) 763c9b1e834SJeeja KP { 764c9b1e834SJeeja KP dev_dbg(ctx->dev, "%s: pipe_satate = %d\n", __func__, state); 765c9b1e834SJeeja KP 766c9b1e834SJeeja KP return skl_ipc_set_pipeline_state(&ctx->ipc, pipe->ppl_id, state); 767c9b1e834SJeeja KP } 768c9b1e834SJeeja KP 769c9b1e834SJeeja KP /* 770c9b1e834SJeeja KP * A pipeline is a collection of modules. Before a module in instantiated a 771c9b1e834SJeeja KP * pipeline needs to be created for it. 772c9b1e834SJeeja KP * This function creates pipeline, by sending create pipeline IPC messages 773c9b1e834SJeeja KP * to FW 774c9b1e834SJeeja KP */ 775c9b1e834SJeeja KP int skl_create_pipeline(struct skl_sst *ctx, struct skl_pipe *pipe) 776c9b1e834SJeeja KP { 777c9b1e834SJeeja KP int ret; 778c9b1e834SJeeja KP 779c9b1e834SJeeja KP dev_dbg(ctx->dev, "%s: pipe_id = %d\n", __func__, pipe->ppl_id); 780c9b1e834SJeeja KP 781c9b1e834SJeeja KP ret = skl_ipc_create_pipeline(&ctx->ipc, pipe->memory_pages, 782c9b1e834SJeeja KP pipe->pipe_priority, pipe->ppl_id); 783c9b1e834SJeeja KP if (ret < 0) { 784c9b1e834SJeeja KP dev_err(ctx->dev, "Failed to create pipeline\n"); 785c9b1e834SJeeja KP return ret; 786c9b1e834SJeeja KP } 787c9b1e834SJeeja KP 788c9b1e834SJeeja KP pipe->state = SKL_PIPE_CREATED; 789c9b1e834SJeeja KP 790c9b1e834SJeeja KP return 0; 791c9b1e834SJeeja KP } 792c9b1e834SJeeja KP 793c9b1e834SJeeja KP /* 794c9b1e834SJeeja KP * A pipeline needs to be deleted on cleanup. If a pipeline is running, then 795c9b1e834SJeeja KP * pause the pipeline first and then delete it 796c9b1e834SJeeja KP * The pipe delete is done by sending delete pipeline IPC. DSP will stop the 797c9b1e834SJeeja KP * DMA engines and releases resources 798c9b1e834SJeeja KP */ 799c9b1e834SJeeja KP int skl_delete_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) 800c9b1e834SJeeja KP { 801c9b1e834SJeeja KP int ret; 802c9b1e834SJeeja KP 803c9b1e834SJeeja KP dev_dbg(ctx->dev, "%s: pipe = %d\n", __func__, pipe->ppl_id); 804c9b1e834SJeeja KP 805c9b1e834SJeeja KP /* If pipe is not started, do not try to stop the pipe in FW. */ 806c9b1e834SJeeja KP if (pipe->state > SKL_PIPE_STARTED) { 807c9b1e834SJeeja KP ret = skl_set_pipe_state(ctx, pipe, PPL_PAUSED); 808c9b1e834SJeeja KP if (ret < 0) { 809c9b1e834SJeeja KP dev_err(ctx->dev, "Failed to stop pipeline\n"); 810c9b1e834SJeeja KP return ret; 811c9b1e834SJeeja KP } 812c9b1e834SJeeja KP 813c9b1e834SJeeja KP pipe->state = SKL_PIPE_PAUSED; 814c9b1e834SJeeja KP } else { 815c9b1e834SJeeja KP /* If pipe was not created in FW, do not try to delete it */ 816c9b1e834SJeeja KP if (pipe->state < SKL_PIPE_CREATED) 817c9b1e834SJeeja KP return 0; 818c9b1e834SJeeja KP 819c9b1e834SJeeja KP ret = skl_ipc_delete_pipeline(&ctx->ipc, pipe->ppl_id); 820c9b1e834SJeeja KP if (ret < 0) 821c9b1e834SJeeja KP dev_err(ctx->dev, "Failed to delete pipeline\n"); 822c9b1e834SJeeja KP } 823c9b1e834SJeeja KP 824c9b1e834SJeeja KP return ret; 825c9b1e834SJeeja KP } 826c9b1e834SJeeja KP 827c9b1e834SJeeja KP /* 828c9b1e834SJeeja KP * A pipeline is also a scheduling entity in DSP which can be run, stopped 829c9b1e834SJeeja KP * For processing data the pipe need to be run by sending IPC set pipe state 830c9b1e834SJeeja KP * to DSP 831c9b1e834SJeeja KP */ 832c9b1e834SJeeja KP int skl_run_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) 833c9b1e834SJeeja KP { 834c9b1e834SJeeja KP int ret; 835c9b1e834SJeeja KP 836c9b1e834SJeeja KP dev_dbg(ctx->dev, "%s: pipe = %d\n", __func__, pipe->ppl_id); 837c9b1e834SJeeja KP 838c9b1e834SJeeja KP /* If pipe was not created in FW, do not try to pause or delete */ 839c9b1e834SJeeja KP if (pipe->state < SKL_PIPE_CREATED) 840c9b1e834SJeeja KP return 0; 841c9b1e834SJeeja KP 842c9b1e834SJeeja KP /* Pipe has to be paused before it is started */ 843c9b1e834SJeeja KP ret = skl_set_pipe_state(ctx, pipe, PPL_PAUSED); 844c9b1e834SJeeja KP if (ret < 0) { 845c9b1e834SJeeja KP dev_err(ctx->dev, "Failed to pause pipe\n"); 846c9b1e834SJeeja KP return ret; 847c9b1e834SJeeja KP } 848c9b1e834SJeeja KP 849c9b1e834SJeeja KP pipe->state = SKL_PIPE_PAUSED; 850c9b1e834SJeeja KP 851c9b1e834SJeeja KP ret = skl_set_pipe_state(ctx, pipe, PPL_RUNNING); 852c9b1e834SJeeja KP if (ret < 0) { 853c9b1e834SJeeja KP dev_err(ctx->dev, "Failed to start pipe\n"); 854c9b1e834SJeeja KP return ret; 855c9b1e834SJeeja KP } 856c9b1e834SJeeja KP 857c9b1e834SJeeja KP pipe->state = SKL_PIPE_STARTED; 858c9b1e834SJeeja KP 859c9b1e834SJeeja KP return 0; 860c9b1e834SJeeja KP } 861c9b1e834SJeeja KP 862c9b1e834SJeeja KP /* 863c9b1e834SJeeja KP * Stop the pipeline by sending set pipe state IPC 864c9b1e834SJeeja KP * DSP doesnt implement stop so we always send pause message 865c9b1e834SJeeja KP */ 866c9b1e834SJeeja KP int skl_stop_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) 867c9b1e834SJeeja KP { 868c9b1e834SJeeja KP int ret; 869c9b1e834SJeeja KP 870c9b1e834SJeeja KP dev_dbg(ctx->dev, "In %s pipe=%d\n", __func__, pipe->ppl_id); 871c9b1e834SJeeja KP 872c9b1e834SJeeja KP /* If pipe was not created in FW, do not try to pause or delete */ 873c9b1e834SJeeja KP if (pipe->state < SKL_PIPE_PAUSED) 874c9b1e834SJeeja KP return 0; 875c9b1e834SJeeja KP 876c9b1e834SJeeja KP ret = skl_set_pipe_state(ctx, pipe, PPL_PAUSED); 877c9b1e834SJeeja KP if (ret < 0) { 878c9b1e834SJeeja KP dev_dbg(ctx->dev, "Failed to stop pipe\n"); 879c9b1e834SJeeja KP return ret; 880c9b1e834SJeeja KP } 881c9b1e834SJeeja KP 882c9b1e834SJeeja KP pipe->state = SKL_PIPE_CREATED; 883c9b1e834SJeeja KP 884c9b1e834SJeeja KP return 0; 885c9b1e834SJeeja KP } 886