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; 215b18c458dSJeeja KP base_cfg->is_pages = mconfig->mem_pages; 21623db472bSJeeja KP } 21723db472bSJeeja KP 21823db472bSJeeja KP /* 21923db472bSJeeja KP * Copies copier capabilities into copier module and updates copier module 22023db472bSJeeja KP * config size. 22123db472bSJeeja KP */ 22223db472bSJeeja KP static void skl_copy_copier_caps(struct skl_module_cfg *mconfig, 22323db472bSJeeja KP struct skl_cpr_cfg *cpr_mconfig) 22423db472bSJeeja KP { 22523db472bSJeeja KP if (mconfig->formats_config.caps_size == 0) 22623db472bSJeeja KP return; 22723db472bSJeeja KP 22823db472bSJeeja KP memcpy(cpr_mconfig->gtw_cfg.config_data, 22923db472bSJeeja KP mconfig->formats_config.caps, 23023db472bSJeeja KP mconfig->formats_config.caps_size); 23123db472bSJeeja KP 23223db472bSJeeja KP cpr_mconfig->gtw_cfg.config_length = 23323db472bSJeeja KP (mconfig->formats_config.caps_size) / 4; 23423db472bSJeeja KP } 23523db472bSJeeja KP 236bfa764acSJeeja KP #define SKL_NON_GATEWAY_CPR_NODE_ID 0xFFFFFFFF 23723db472bSJeeja KP /* 23823db472bSJeeja KP * Calculate the gatewat settings required for copier module, type of 23923db472bSJeeja KP * gateway and index of gateway to use 24023db472bSJeeja KP */ 2414fdf810fSDharageswari.R static u32 skl_get_node_id(struct skl_sst *ctx, 2424fdf810fSDharageswari.R struct skl_module_cfg *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: 2914fdf810fSDharageswari.R node_id.val = 0xFFFFFFFF; 2924fdf810fSDharageswari.R break; 2934fdf810fSDharageswari.R } 2944fdf810fSDharageswari.R 2954fdf810fSDharageswari.R return node_id.val; 2964fdf810fSDharageswari.R } 2974fdf810fSDharageswari.R 2984fdf810fSDharageswari.R static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx, 2994fdf810fSDharageswari.R struct skl_module_cfg *mconfig, 3004fdf810fSDharageswari.R struct skl_cpr_cfg *cpr_mconfig) 3014fdf810fSDharageswari.R { 3024fdf810fSDharageswari.R cpr_mconfig->gtw_cfg.node_id = skl_get_node_id(ctx, mconfig); 3034fdf810fSDharageswari.R 3044fdf810fSDharageswari.R if (cpr_mconfig->gtw_cfg.node_id == SKL_NON_GATEWAY_CPR_NODE_ID) { 305bfa764acSJeeja KP cpr_mconfig->cpr_feature_mask = 0; 306bfa764acSJeeja KP return; 30723db472bSJeeja KP } 30823db472bSJeeja KP 30923db472bSJeeja KP if (SKL_CONN_SOURCE == mconfig->hw_conn_type) 31023db472bSJeeja KP cpr_mconfig->gtw_cfg.dma_buffer_size = 2 * mconfig->obs; 31123db472bSJeeja KP else 31223db472bSJeeja KP cpr_mconfig->gtw_cfg.dma_buffer_size = 2 * mconfig->ibs; 31323db472bSJeeja KP 31423db472bSJeeja KP cpr_mconfig->cpr_feature_mask = 0; 31523db472bSJeeja KP cpr_mconfig->gtw_cfg.config_length = 0; 31623db472bSJeeja KP 31723db472bSJeeja KP skl_copy_copier_caps(mconfig, cpr_mconfig); 31823db472bSJeeja KP } 31923db472bSJeeja KP 32023db472bSJeeja KP static void skl_setup_out_format(struct skl_sst *ctx, 32123db472bSJeeja KP struct skl_module_cfg *mconfig, 32223db472bSJeeja KP struct skl_audio_data_format *out_fmt) 32323db472bSJeeja KP { 3244cd9899fSHardik T Shah struct skl_module_fmt *format = &mconfig->out_fmt[0]; 32523db472bSJeeja KP 32623db472bSJeeja KP out_fmt->number_of_channels = (u8)format->channels; 32723db472bSJeeja KP out_fmt->s_freq = format->s_freq; 32823db472bSJeeja KP out_fmt->bit_depth = format->bit_depth; 32923db472bSJeeja KP out_fmt->valid_bit_depth = format->valid_bit_depth; 33023db472bSJeeja KP out_fmt->ch_cfg = format->ch_cfg; 33123db472bSJeeja KP 3323e81f1a3SJeeja KP out_fmt->channel_map = format->ch_map; 3333e81f1a3SJeeja KP out_fmt->interleaving = format->interleaving_style; 3343e81f1a3SJeeja KP out_fmt->sample_type = format->sample_type; 33523db472bSJeeja KP 33623db472bSJeeja KP dev_dbg(ctx->dev, "copier out format chan=%d fre=%d bitdepth=%d\n", 33723db472bSJeeja KP out_fmt->number_of_channels, format->s_freq, format->bit_depth); 33823db472bSJeeja KP } 33923db472bSJeeja KP 34023db472bSJeeja KP /* 341a0ffe48bSHardik T Shah * DSP needs SRC module for frequency conversion, SRC takes base module 342a0ffe48bSHardik T Shah * configuration and the target frequency as extra parameter passed as src 343a0ffe48bSHardik T Shah * config 344a0ffe48bSHardik T Shah */ 345a0ffe48bSHardik T Shah static void skl_set_src_format(struct skl_sst *ctx, 346a0ffe48bSHardik T Shah struct skl_module_cfg *mconfig, 347a0ffe48bSHardik T Shah struct skl_src_module_cfg *src_mconfig) 348a0ffe48bSHardik T Shah { 3494cd9899fSHardik T Shah struct skl_module_fmt *fmt = &mconfig->out_fmt[0]; 350a0ffe48bSHardik T Shah 351a0ffe48bSHardik T Shah skl_set_base_module_format(ctx, mconfig, 352a0ffe48bSHardik T Shah (struct skl_base_cfg *)src_mconfig); 353a0ffe48bSHardik T Shah 354a0ffe48bSHardik T Shah src_mconfig->src_cfg = fmt->s_freq; 355a0ffe48bSHardik T Shah } 356a0ffe48bSHardik T Shah 357a0ffe48bSHardik T Shah /* 358a0ffe48bSHardik T Shah * DSP needs updown module to do channel conversion. updown module take base 359a0ffe48bSHardik T Shah * module configuration and channel configuration 360a0ffe48bSHardik T Shah * It also take coefficients and now we have defaults applied here 361a0ffe48bSHardik T Shah */ 362a0ffe48bSHardik T Shah static void skl_set_updown_mixer_format(struct skl_sst *ctx, 363a0ffe48bSHardik T Shah struct skl_module_cfg *mconfig, 364a0ffe48bSHardik T Shah struct skl_up_down_mixer_cfg *mixer_mconfig) 365a0ffe48bSHardik T Shah { 3664cd9899fSHardik T Shah struct skl_module_fmt *fmt = &mconfig->out_fmt[0]; 367a0ffe48bSHardik T Shah int i = 0; 368a0ffe48bSHardik T Shah 369a0ffe48bSHardik T Shah skl_set_base_module_format(ctx, mconfig, 370a0ffe48bSHardik T Shah (struct skl_base_cfg *)mixer_mconfig); 371a0ffe48bSHardik T Shah mixer_mconfig->out_ch_cfg = fmt->ch_cfg; 372a0ffe48bSHardik T Shah 373a0ffe48bSHardik T Shah /* Select F/W default coefficient */ 374a0ffe48bSHardik T Shah mixer_mconfig->coeff_sel = 0x0; 375a0ffe48bSHardik T Shah 376a0ffe48bSHardik T Shah /* User coeff, don't care since we are selecting F/W defaults */ 377a0ffe48bSHardik T Shah for (i = 0; i < UP_DOWN_MIXER_MAX_COEFF; i++) 378a0ffe48bSHardik T Shah mixer_mconfig->coeff[i] = 0xDEADBEEF; 379a0ffe48bSHardik T Shah } 380a0ffe48bSHardik T Shah 381a0ffe48bSHardik T Shah /* 38223db472bSJeeja KP * 'copier' is DSP internal module which copies data from Host DMA (HDA host 38323db472bSJeeja KP * dma) or link (hda link, SSP, PDM) 38423db472bSJeeja KP * Here we calculate the copier module parameters, like PCM format, output 38523db472bSJeeja KP * format, gateway settings 38623db472bSJeeja KP * copier_module_config is sent as input buffer with INIT_INSTANCE IPC msg 38723db472bSJeeja KP */ 38823db472bSJeeja KP static void skl_set_copier_format(struct skl_sst *ctx, 38923db472bSJeeja KP struct skl_module_cfg *mconfig, 39023db472bSJeeja KP struct skl_cpr_cfg *cpr_mconfig) 39123db472bSJeeja KP { 39223db472bSJeeja KP struct skl_audio_data_format *out_fmt = &cpr_mconfig->out_fmt; 39323db472bSJeeja KP struct skl_base_cfg *base_cfg = (struct skl_base_cfg *)cpr_mconfig; 39423db472bSJeeja KP 39523db472bSJeeja KP skl_set_base_module_format(ctx, mconfig, base_cfg); 39623db472bSJeeja KP 39723db472bSJeeja KP skl_setup_out_format(ctx, mconfig, out_fmt); 39823db472bSJeeja KP skl_setup_cpr_gateway_cfg(ctx, mconfig, cpr_mconfig); 39923db472bSJeeja KP } 40023db472bSJeeja KP 401399b210bSJeeja KP /* 402399b210bSJeeja KP * Algo module are DSP pre processing modules. Algo module take base module 403399b210bSJeeja KP * configuration and params 404399b210bSJeeja KP */ 405399b210bSJeeja KP 406399b210bSJeeja KP static void skl_set_algo_format(struct skl_sst *ctx, 407399b210bSJeeja KP struct skl_module_cfg *mconfig, 408399b210bSJeeja KP struct skl_algo_cfg *algo_mcfg) 409399b210bSJeeja KP { 410399b210bSJeeja KP struct skl_base_cfg *base_cfg = (struct skl_base_cfg *)algo_mcfg; 411399b210bSJeeja KP 412399b210bSJeeja KP skl_set_base_module_format(ctx, mconfig, base_cfg); 413399b210bSJeeja KP 414399b210bSJeeja KP if (mconfig->formats_config.caps_size == 0) 415399b210bSJeeja KP return; 416399b210bSJeeja KP 417399b210bSJeeja KP memcpy(algo_mcfg->params, 418399b210bSJeeja KP mconfig->formats_config.caps, 419399b210bSJeeja KP mconfig->formats_config.caps_size); 420399b210bSJeeja KP 421399b210bSJeeja KP } 422399b210bSJeeja KP 423fd18110fSDharageswari R /* 424fd18110fSDharageswari R * Mic select module allows selecting one or many input channels, thus 425fd18110fSDharageswari R * acting as a demux. 426fd18110fSDharageswari R * 427fd18110fSDharageswari R * Mic select module take base module configuration and out-format 428fd18110fSDharageswari R * configuration 429fd18110fSDharageswari R */ 430fd18110fSDharageswari R static void skl_set_base_outfmt_format(struct skl_sst *ctx, 431fd18110fSDharageswari R struct skl_module_cfg *mconfig, 432fd18110fSDharageswari R struct skl_base_outfmt_cfg *base_outfmt_mcfg) 433fd18110fSDharageswari R { 434fd18110fSDharageswari R struct skl_audio_data_format *out_fmt = &base_outfmt_mcfg->out_fmt; 435fd18110fSDharageswari R struct skl_base_cfg *base_cfg = 436fd18110fSDharageswari R (struct skl_base_cfg *)base_outfmt_mcfg; 437fd18110fSDharageswari R 438fd18110fSDharageswari R skl_set_base_module_format(ctx, mconfig, base_cfg); 439fd18110fSDharageswari R skl_setup_out_format(ctx, mconfig, out_fmt); 440fd18110fSDharageswari R } 441fd18110fSDharageswari R 44223db472bSJeeja KP static u16 skl_get_module_param_size(struct skl_sst *ctx, 44323db472bSJeeja KP struct skl_module_cfg *mconfig) 44423db472bSJeeja KP { 44523db472bSJeeja KP u16 param_size; 44623db472bSJeeja KP 44723db472bSJeeja KP switch (mconfig->m_type) { 44823db472bSJeeja KP case SKL_MODULE_TYPE_COPIER: 44923db472bSJeeja KP param_size = sizeof(struct skl_cpr_cfg); 45023db472bSJeeja KP param_size += mconfig->formats_config.caps_size; 45123db472bSJeeja KP return param_size; 45223db472bSJeeja KP 453a0ffe48bSHardik T Shah case SKL_MODULE_TYPE_SRCINT: 454a0ffe48bSHardik T Shah return sizeof(struct skl_src_module_cfg); 455a0ffe48bSHardik T Shah 456a0ffe48bSHardik T Shah case SKL_MODULE_TYPE_UPDWMIX: 457a0ffe48bSHardik T Shah return sizeof(struct skl_up_down_mixer_cfg); 458a0ffe48bSHardik T Shah 459399b210bSJeeja KP case SKL_MODULE_TYPE_ALGO: 460399b210bSJeeja KP param_size = sizeof(struct skl_base_cfg); 461399b210bSJeeja KP param_size += mconfig->formats_config.caps_size; 462399b210bSJeeja KP return param_size; 463399b210bSJeeja KP 464fd18110fSDharageswari R case SKL_MODULE_TYPE_BASE_OUTFMT: 465fd18110fSDharageswari R return sizeof(struct skl_base_outfmt_cfg); 466fd18110fSDharageswari R 46723db472bSJeeja KP default: 46823db472bSJeeja KP /* 46923db472bSJeeja KP * return only base cfg when no specific module type is 47023db472bSJeeja KP * specified 47123db472bSJeeja KP */ 47223db472bSJeeja KP return sizeof(struct skl_base_cfg); 47323db472bSJeeja KP } 47423db472bSJeeja KP 47523db472bSJeeja KP return 0; 47623db472bSJeeja KP } 47723db472bSJeeja KP 47823db472bSJeeja KP /* 479a0ffe48bSHardik T Shah * DSP firmware supports various modules like copier, SRC, updown etc. 480a0ffe48bSHardik T Shah * These modules required various parameters to be calculated and sent for 481a0ffe48bSHardik T Shah * the module initialization to DSP. By default a generic module needs only 482a0ffe48bSHardik T Shah * base module format configuration 48323db472bSJeeja KP */ 484a0ffe48bSHardik T Shah 48523db472bSJeeja KP static int skl_set_module_format(struct skl_sst *ctx, 48623db472bSJeeja KP struct skl_module_cfg *module_config, 48723db472bSJeeja KP u16 *module_config_size, 48823db472bSJeeja KP void **param_data) 48923db472bSJeeja KP { 49023db472bSJeeja KP u16 param_size; 49123db472bSJeeja KP 49223db472bSJeeja KP param_size = skl_get_module_param_size(ctx, module_config); 49323db472bSJeeja KP 49423db472bSJeeja KP *param_data = kzalloc(param_size, GFP_KERNEL); 49523db472bSJeeja KP if (NULL == *param_data) 49623db472bSJeeja KP return -ENOMEM; 49723db472bSJeeja KP 49823db472bSJeeja KP *module_config_size = param_size; 49923db472bSJeeja KP 50023db472bSJeeja KP switch (module_config->m_type) { 50123db472bSJeeja KP case SKL_MODULE_TYPE_COPIER: 50223db472bSJeeja KP skl_set_copier_format(ctx, module_config, *param_data); 50323db472bSJeeja KP break; 50423db472bSJeeja KP 505a0ffe48bSHardik T Shah case SKL_MODULE_TYPE_SRCINT: 506a0ffe48bSHardik T Shah skl_set_src_format(ctx, module_config, *param_data); 507a0ffe48bSHardik T Shah break; 508a0ffe48bSHardik T Shah 509a0ffe48bSHardik T Shah case SKL_MODULE_TYPE_UPDWMIX: 510a0ffe48bSHardik T Shah skl_set_updown_mixer_format(ctx, module_config, *param_data); 511a0ffe48bSHardik T Shah break; 512a0ffe48bSHardik T Shah 513399b210bSJeeja KP case SKL_MODULE_TYPE_ALGO: 514399b210bSJeeja KP skl_set_algo_format(ctx, module_config, *param_data); 515399b210bSJeeja KP break; 516399b210bSJeeja KP 517fd18110fSDharageswari R case SKL_MODULE_TYPE_BASE_OUTFMT: 518fd18110fSDharageswari R skl_set_base_outfmt_format(ctx, module_config, *param_data); 519fd18110fSDharageswari R break; 520fd18110fSDharageswari R 52123db472bSJeeja KP default: 52223db472bSJeeja KP skl_set_base_module_format(ctx, module_config, *param_data); 52323db472bSJeeja KP break; 52423db472bSJeeja KP 52523db472bSJeeja KP } 52623db472bSJeeja KP 52723db472bSJeeja KP dev_dbg(ctx->dev, "Module type=%d config size: %d bytes\n", 52823db472bSJeeja KP module_config->id.module_id, param_size); 52923db472bSJeeja KP print_hex_dump(KERN_DEBUG, "Module params:", DUMP_PREFIX_OFFSET, 8, 4, 53023db472bSJeeja KP *param_data, param_size, false); 53123db472bSJeeja KP return 0; 53223db472bSJeeja KP } 53323db472bSJeeja KP 53423db472bSJeeja KP static int skl_get_queue_index(struct skl_module_pin *mpin, 53523db472bSJeeja KP struct skl_module_inst_id id, int max) 53623db472bSJeeja KP { 53723db472bSJeeja KP int i; 53823db472bSJeeja KP 53923db472bSJeeja KP for (i = 0; i < max; i++) { 54023db472bSJeeja KP if (mpin[i].id.module_id == id.module_id && 54123db472bSJeeja KP mpin[i].id.instance_id == id.instance_id) 54223db472bSJeeja KP return i; 54323db472bSJeeja KP } 54423db472bSJeeja KP 54523db472bSJeeja KP return -EINVAL; 54623db472bSJeeja KP } 54723db472bSJeeja KP 54823db472bSJeeja KP /* 54923db472bSJeeja KP * Allocates queue for each module. 55023db472bSJeeja KP * if dynamic, the pin_index is allocated 0 to max_pin. 55123db472bSJeeja KP * In static, the pin_index is fixed based on module_id and instance id 55223db472bSJeeja KP */ 55323db472bSJeeja KP static int skl_alloc_queue(struct skl_module_pin *mpin, 5544f745708SJeeja KP struct skl_module_cfg *tgt_cfg, int max) 55523db472bSJeeja KP { 55623db472bSJeeja KP int i; 5574f745708SJeeja KP struct skl_module_inst_id id = tgt_cfg->id; 55823db472bSJeeja KP /* 55923db472bSJeeja KP * if pin in dynamic, find first free pin 56023db472bSJeeja KP * otherwise find match module and instance id pin as topology will 56123db472bSJeeja KP * ensure a unique pin is assigned to this so no need to 56223db472bSJeeja KP * allocate/free 56323db472bSJeeja KP */ 56423db472bSJeeja KP for (i = 0; i < max; i++) { 56523db472bSJeeja KP if (mpin[i].is_dynamic) { 5664f745708SJeeja KP if (!mpin[i].in_use && 5674f745708SJeeja KP mpin[i].pin_state == SKL_PIN_UNBIND) { 5684f745708SJeeja KP 56923db472bSJeeja KP mpin[i].in_use = true; 57023db472bSJeeja KP mpin[i].id.module_id = id.module_id; 57123db472bSJeeja KP mpin[i].id.instance_id = id.instance_id; 5724f745708SJeeja KP mpin[i].tgt_mcfg = tgt_cfg; 57323db472bSJeeja KP return i; 57423db472bSJeeja KP } 57523db472bSJeeja KP } else { 57623db472bSJeeja KP if (mpin[i].id.module_id == id.module_id && 5774f745708SJeeja KP mpin[i].id.instance_id == id.instance_id && 5784f745708SJeeja KP mpin[i].pin_state == SKL_PIN_UNBIND) { 5794f745708SJeeja KP 5804f745708SJeeja KP mpin[i].tgt_mcfg = tgt_cfg; 58123db472bSJeeja KP return i; 58223db472bSJeeja KP } 58323db472bSJeeja KP } 5844f745708SJeeja KP } 58523db472bSJeeja KP 58623db472bSJeeja KP return -EINVAL; 58723db472bSJeeja KP } 58823db472bSJeeja KP 58923db472bSJeeja KP static void skl_free_queue(struct skl_module_pin *mpin, int q_index) 59023db472bSJeeja KP { 59123db472bSJeeja KP if (mpin[q_index].is_dynamic) { 59223db472bSJeeja KP mpin[q_index].in_use = false; 59323db472bSJeeja KP mpin[q_index].id.module_id = 0; 59423db472bSJeeja KP mpin[q_index].id.instance_id = 0; 59523db472bSJeeja KP } 5964f745708SJeeja KP mpin[q_index].pin_state = SKL_PIN_UNBIND; 5974f745708SJeeja KP mpin[q_index].tgt_mcfg = NULL; 5984f745708SJeeja KP } 5994f745708SJeeja KP 6004f745708SJeeja KP /* Module state will be set to unint, if all the out pin state is UNBIND */ 6014f745708SJeeja KP 6024f745708SJeeja KP static void skl_clear_module_state(struct skl_module_pin *mpin, int max, 6034f745708SJeeja KP struct skl_module_cfg *mcfg) 6044f745708SJeeja KP { 6054f745708SJeeja KP int i; 6064f745708SJeeja KP bool found = false; 6074f745708SJeeja KP 6084f745708SJeeja KP for (i = 0; i < max; i++) { 6094f745708SJeeja KP if (mpin[i].pin_state == SKL_PIN_UNBIND) 6104f745708SJeeja KP continue; 6114f745708SJeeja KP found = true; 6124f745708SJeeja KP break; 6134f745708SJeeja KP } 6144f745708SJeeja KP 6154f745708SJeeja KP if (!found) 6164f745708SJeeja KP mcfg->m_state = SKL_MODULE_UNINIT; 6174f745708SJeeja KP return; 61823db472bSJeeja KP } 619beb73b26SJeeja KP 620beb73b26SJeeja KP /* 621beb73b26SJeeja KP * A module needs to be instanataited in DSP. A mdoule is present in a 622beb73b26SJeeja KP * collection of module referred as a PIPE. 623beb73b26SJeeja KP * We first calculate the module format, based on module type and then 624beb73b26SJeeja KP * invoke the DSP by sending IPC INIT_INSTANCE using ipc helper 625beb73b26SJeeja KP */ 626beb73b26SJeeja KP int skl_init_module(struct skl_sst *ctx, 6279939a9c3SJeeja KP struct skl_module_cfg *mconfig) 628beb73b26SJeeja KP { 629beb73b26SJeeja KP u16 module_config_size = 0; 630beb73b26SJeeja KP void *param_data = NULL; 631beb73b26SJeeja KP int ret; 632beb73b26SJeeja KP struct skl_ipc_init_instance_msg msg; 633beb73b26SJeeja KP 634beb73b26SJeeja KP dev_dbg(ctx->dev, "%s: module_id = %d instance=%d\n", __func__, 635beb73b26SJeeja KP mconfig->id.module_id, mconfig->id.instance_id); 636beb73b26SJeeja KP 637beb73b26SJeeja KP if (mconfig->pipe->state != SKL_PIPE_CREATED) { 638beb73b26SJeeja KP dev_err(ctx->dev, "Pipe not created state= %d pipe_id= %d\n", 639beb73b26SJeeja KP mconfig->pipe->state, mconfig->pipe->ppl_id); 640beb73b26SJeeja KP return -EIO; 641beb73b26SJeeja KP } 642beb73b26SJeeja KP 643beb73b26SJeeja KP ret = skl_set_module_format(ctx, mconfig, 644beb73b26SJeeja KP &module_config_size, ¶m_data); 645beb73b26SJeeja KP if (ret < 0) { 646beb73b26SJeeja KP dev_err(ctx->dev, "Failed to set module format ret=%d\n", ret); 647beb73b26SJeeja KP return ret; 648beb73b26SJeeja KP } 649beb73b26SJeeja KP 650beb73b26SJeeja KP msg.module_id = mconfig->id.module_id; 651beb73b26SJeeja KP msg.instance_id = mconfig->id.instance_id; 652beb73b26SJeeja KP msg.ppl_instance_id = mconfig->pipe->ppl_id; 653beb73b26SJeeja KP msg.param_data_size = module_config_size; 654beb73b26SJeeja KP msg.core_id = mconfig->core_id; 655beb73b26SJeeja KP 656beb73b26SJeeja KP ret = skl_ipc_init_instance(&ctx->ipc, &msg, param_data); 657beb73b26SJeeja KP if (ret < 0) { 658beb73b26SJeeja KP dev_err(ctx->dev, "Failed to init instance ret=%d\n", ret); 659beb73b26SJeeja KP kfree(param_data); 660beb73b26SJeeja KP return ret; 661beb73b26SJeeja KP } 662beb73b26SJeeja KP mconfig->m_state = SKL_MODULE_INIT_DONE; 663beb73b26SJeeja KP 664beb73b26SJeeja KP return ret; 665beb73b26SJeeja KP } 666beb73b26SJeeja KP 667beb73b26SJeeja KP static void skl_dump_bind_info(struct skl_sst *ctx, struct skl_module_cfg 668beb73b26SJeeja KP *src_module, struct skl_module_cfg *dst_module) 669beb73b26SJeeja KP { 670beb73b26SJeeja KP dev_dbg(ctx->dev, "%s: src module_id = %d src_instance=%d\n", 671beb73b26SJeeja KP __func__, src_module->id.module_id, src_module->id.instance_id); 672beb73b26SJeeja KP dev_dbg(ctx->dev, "%s: dst_module=%d dst_instacne=%d\n", __func__, 673beb73b26SJeeja KP dst_module->id.module_id, dst_module->id.instance_id); 674beb73b26SJeeja KP 675beb73b26SJeeja KP dev_dbg(ctx->dev, "src_module state = %d dst module state = %d\n", 676beb73b26SJeeja KP src_module->m_state, dst_module->m_state); 677beb73b26SJeeja KP } 678beb73b26SJeeja KP 679beb73b26SJeeja KP /* 680beb73b26SJeeja KP * On module freeup, we need to unbind the module with modules 681beb73b26SJeeja KP * it is already bind. 682beb73b26SJeeja KP * Find the pin allocated and unbind then using bind_unbind IPC 683beb73b26SJeeja KP */ 684beb73b26SJeeja KP int skl_unbind_modules(struct skl_sst *ctx, 685beb73b26SJeeja KP struct skl_module_cfg *src_mcfg, 686beb73b26SJeeja KP struct skl_module_cfg *dst_mcfg) 687beb73b26SJeeja KP { 688beb73b26SJeeja KP int ret; 689beb73b26SJeeja KP struct skl_ipc_bind_unbind_msg msg; 690beb73b26SJeeja KP struct skl_module_inst_id src_id = src_mcfg->id; 691beb73b26SJeeja KP struct skl_module_inst_id dst_id = dst_mcfg->id; 692beb73b26SJeeja KP int in_max = dst_mcfg->max_in_queue; 693beb73b26SJeeja KP int out_max = src_mcfg->max_out_queue; 6944f745708SJeeja KP int src_index, dst_index, src_pin_state, dst_pin_state; 695beb73b26SJeeja KP 696beb73b26SJeeja KP skl_dump_bind_info(ctx, src_mcfg, dst_mcfg); 697beb73b26SJeeja KP 698beb73b26SJeeja KP /* get src queue index */ 699beb73b26SJeeja KP src_index = skl_get_queue_index(src_mcfg->m_out_pin, dst_id, out_max); 700beb73b26SJeeja KP if (src_index < 0) 7019cf3049eSJeeja KP return 0; 702beb73b26SJeeja KP 7034f745708SJeeja KP msg.src_queue = src_index; 704beb73b26SJeeja KP 705beb73b26SJeeja KP /* get dst queue index */ 706beb73b26SJeeja KP dst_index = skl_get_queue_index(dst_mcfg->m_in_pin, src_id, in_max); 707beb73b26SJeeja KP if (dst_index < 0) 7089cf3049eSJeeja KP return 0; 709beb73b26SJeeja KP 7104f745708SJeeja KP msg.dst_queue = dst_index; 7114f745708SJeeja KP 7124f745708SJeeja KP src_pin_state = src_mcfg->m_out_pin[src_index].pin_state; 7134f745708SJeeja KP dst_pin_state = dst_mcfg->m_in_pin[dst_index].pin_state; 7144f745708SJeeja KP 7154f745708SJeeja KP if (src_pin_state != SKL_PIN_BIND_DONE || 7164f745708SJeeja KP dst_pin_state != SKL_PIN_BIND_DONE) 7174f745708SJeeja KP return 0; 718beb73b26SJeeja KP 719beb73b26SJeeja KP msg.module_id = src_mcfg->id.module_id; 720beb73b26SJeeja KP msg.instance_id = src_mcfg->id.instance_id; 721beb73b26SJeeja KP msg.dst_module_id = dst_mcfg->id.module_id; 722beb73b26SJeeja KP msg.dst_instance_id = dst_mcfg->id.instance_id; 723beb73b26SJeeja KP msg.bind = false; 724beb73b26SJeeja KP 725beb73b26SJeeja KP ret = skl_ipc_bind_unbind(&ctx->ipc, &msg); 726beb73b26SJeeja KP if (!ret) { 727beb73b26SJeeja KP /* free queue only if unbind is success */ 728beb73b26SJeeja KP skl_free_queue(src_mcfg->m_out_pin, src_index); 729beb73b26SJeeja KP skl_free_queue(dst_mcfg->m_in_pin, dst_index); 7304f745708SJeeja KP 7314f745708SJeeja KP /* 7324f745708SJeeja KP * check only if src module bind state, bind is 7334f745708SJeeja KP * always from src -> sink 7344f745708SJeeja KP */ 7354f745708SJeeja KP skl_clear_module_state(src_mcfg->m_out_pin, out_max, src_mcfg); 736beb73b26SJeeja KP } 737beb73b26SJeeja KP 738beb73b26SJeeja KP return ret; 739beb73b26SJeeja KP } 740beb73b26SJeeja KP 741beb73b26SJeeja KP /* 742beb73b26SJeeja KP * Once a module is instantiated it need to be 'bind' with other modules in 743beb73b26SJeeja KP * the pipeline. For binding we need to find the module pins which are bind 744beb73b26SJeeja KP * together 745beb73b26SJeeja KP * This function finds the pins and then sends bund_unbind IPC message to 746beb73b26SJeeja KP * DSP using IPC helper 747beb73b26SJeeja KP */ 748beb73b26SJeeja KP int skl_bind_modules(struct skl_sst *ctx, 749beb73b26SJeeja KP struct skl_module_cfg *src_mcfg, 750beb73b26SJeeja KP struct skl_module_cfg *dst_mcfg) 751beb73b26SJeeja KP { 752beb73b26SJeeja KP int ret; 753beb73b26SJeeja KP struct skl_ipc_bind_unbind_msg msg; 754beb73b26SJeeja KP int in_max = dst_mcfg->max_in_queue; 755beb73b26SJeeja KP int out_max = src_mcfg->max_out_queue; 756beb73b26SJeeja KP int src_index, dst_index; 757beb73b26SJeeja KP 758beb73b26SJeeja KP skl_dump_bind_info(ctx, src_mcfg, dst_mcfg); 759beb73b26SJeeja KP 7600c684c48SJeeja KP if (src_mcfg->m_state < SKL_MODULE_INIT_DONE || 761beb73b26SJeeja KP dst_mcfg->m_state < SKL_MODULE_INIT_DONE) 762beb73b26SJeeja KP return 0; 763beb73b26SJeeja KP 7644f745708SJeeja KP src_index = skl_alloc_queue(src_mcfg->m_out_pin, dst_mcfg, out_max); 765beb73b26SJeeja KP if (src_index < 0) 766beb73b26SJeeja KP return -EINVAL; 767beb73b26SJeeja KP 7684f745708SJeeja KP msg.src_queue = src_index; 7694f745708SJeeja KP dst_index = skl_alloc_queue(dst_mcfg->m_in_pin, src_mcfg, in_max); 770beb73b26SJeeja KP if (dst_index < 0) { 771beb73b26SJeeja KP skl_free_queue(src_mcfg->m_out_pin, src_index); 772beb73b26SJeeja KP return -EINVAL; 773beb73b26SJeeja KP } 774beb73b26SJeeja KP 7754f745708SJeeja KP msg.dst_queue = dst_index; 776beb73b26SJeeja KP 777beb73b26SJeeja KP dev_dbg(ctx->dev, "src queue = %d dst queue =%d\n", 778beb73b26SJeeja KP msg.src_queue, msg.dst_queue); 779beb73b26SJeeja KP 780beb73b26SJeeja KP msg.module_id = src_mcfg->id.module_id; 781beb73b26SJeeja KP msg.instance_id = src_mcfg->id.instance_id; 782beb73b26SJeeja KP msg.dst_module_id = dst_mcfg->id.module_id; 783beb73b26SJeeja KP msg.dst_instance_id = dst_mcfg->id.instance_id; 784beb73b26SJeeja KP msg.bind = true; 785beb73b26SJeeja KP 786beb73b26SJeeja KP ret = skl_ipc_bind_unbind(&ctx->ipc, &msg); 787beb73b26SJeeja KP 788beb73b26SJeeja KP if (!ret) { 789beb73b26SJeeja KP src_mcfg->m_state = SKL_MODULE_BIND_DONE; 7904f745708SJeeja KP src_mcfg->m_out_pin[src_index].pin_state = SKL_PIN_BIND_DONE; 7914f745708SJeeja KP dst_mcfg->m_in_pin[dst_index].pin_state = SKL_PIN_BIND_DONE; 792beb73b26SJeeja KP } else { 793beb73b26SJeeja KP /* error case , if IPC fails, clear the queue index */ 794beb73b26SJeeja KP skl_free_queue(src_mcfg->m_out_pin, src_index); 795beb73b26SJeeja KP skl_free_queue(dst_mcfg->m_in_pin, dst_index); 796beb73b26SJeeja KP } 797beb73b26SJeeja KP 798beb73b26SJeeja KP return ret; 799beb73b26SJeeja KP } 800c9b1e834SJeeja KP 801c9b1e834SJeeja KP static int skl_set_pipe_state(struct skl_sst *ctx, struct skl_pipe *pipe, 802c9b1e834SJeeja KP enum skl_ipc_pipeline_state state) 803c9b1e834SJeeja KP { 804c9b1e834SJeeja KP dev_dbg(ctx->dev, "%s: pipe_satate = %d\n", __func__, state); 805c9b1e834SJeeja KP 806c9b1e834SJeeja KP return skl_ipc_set_pipeline_state(&ctx->ipc, pipe->ppl_id, state); 807c9b1e834SJeeja KP } 808c9b1e834SJeeja KP 809c9b1e834SJeeja KP /* 810c9b1e834SJeeja KP * A pipeline is a collection of modules. Before a module in instantiated a 811c9b1e834SJeeja KP * pipeline needs to be created for it. 812c9b1e834SJeeja KP * This function creates pipeline, by sending create pipeline IPC messages 813c9b1e834SJeeja KP * to FW 814c9b1e834SJeeja KP */ 815c9b1e834SJeeja KP int skl_create_pipeline(struct skl_sst *ctx, struct skl_pipe *pipe) 816c9b1e834SJeeja KP { 817c9b1e834SJeeja KP int ret; 818c9b1e834SJeeja KP 819c9b1e834SJeeja KP dev_dbg(ctx->dev, "%s: pipe_id = %d\n", __func__, pipe->ppl_id); 820c9b1e834SJeeja KP 821c9b1e834SJeeja KP ret = skl_ipc_create_pipeline(&ctx->ipc, pipe->memory_pages, 822c9b1e834SJeeja KP pipe->pipe_priority, pipe->ppl_id); 823c9b1e834SJeeja KP if (ret < 0) { 824c9b1e834SJeeja KP dev_err(ctx->dev, "Failed to create pipeline\n"); 825c9b1e834SJeeja KP return ret; 826c9b1e834SJeeja KP } 827c9b1e834SJeeja KP 828c9b1e834SJeeja KP pipe->state = SKL_PIPE_CREATED; 829c9b1e834SJeeja KP 830c9b1e834SJeeja KP return 0; 831c9b1e834SJeeja KP } 832c9b1e834SJeeja KP 833c9b1e834SJeeja KP /* 834c9b1e834SJeeja KP * A pipeline needs to be deleted on cleanup. If a pipeline is running, then 835c9b1e834SJeeja KP * pause the pipeline first and then delete it 836c9b1e834SJeeja KP * The pipe delete is done by sending delete pipeline IPC. DSP will stop the 837c9b1e834SJeeja KP * DMA engines and releases resources 838c9b1e834SJeeja KP */ 839c9b1e834SJeeja KP int skl_delete_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) 840c9b1e834SJeeja KP { 841c9b1e834SJeeja KP int ret; 842c9b1e834SJeeja KP 843c9b1e834SJeeja KP dev_dbg(ctx->dev, "%s: pipe = %d\n", __func__, pipe->ppl_id); 844c9b1e834SJeeja KP 845c9b1e834SJeeja KP /* If pipe is not started, do not try to stop the pipe in FW. */ 846c9b1e834SJeeja KP if (pipe->state > SKL_PIPE_STARTED) { 847c9b1e834SJeeja KP ret = skl_set_pipe_state(ctx, pipe, PPL_PAUSED); 848c9b1e834SJeeja KP if (ret < 0) { 849c9b1e834SJeeja KP dev_err(ctx->dev, "Failed to stop pipeline\n"); 850c9b1e834SJeeja KP return ret; 851c9b1e834SJeeja KP } 852c9b1e834SJeeja KP 853c9b1e834SJeeja KP pipe->state = SKL_PIPE_PAUSED; 854c9b1e834SJeeja KP } else { 855c9b1e834SJeeja KP /* If pipe was not created in FW, do not try to delete it */ 856c9b1e834SJeeja KP if (pipe->state < SKL_PIPE_CREATED) 857c9b1e834SJeeja KP return 0; 858c9b1e834SJeeja KP 859c9b1e834SJeeja KP ret = skl_ipc_delete_pipeline(&ctx->ipc, pipe->ppl_id); 860c9b1e834SJeeja KP if (ret < 0) 861c9b1e834SJeeja KP dev_err(ctx->dev, "Failed to delete pipeline\n"); 862d2c7db85SJeeja KP 863d2c7db85SJeeja KP pipe->state = SKL_PIPE_INVALID; 864c9b1e834SJeeja KP } 865c9b1e834SJeeja KP 866c9b1e834SJeeja KP return ret; 867c9b1e834SJeeja KP } 868c9b1e834SJeeja KP 869c9b1e834SJeeja KP /* 870c9b1e834SJeeja KP * A pipeline is also a scheduling entity in DSP which can be run, stopped 871c9b1e834SJeeja KP * For processing data the pipe need to be run by sending IPC set pipe state 872c9b1e834SJeeja KP * to DSP 873c9b1e834SJeeja KP */ 874c9b1e834SJeeja KP int skl_run_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) 875c9b1e834SJeeja KP { 876c9b1e834SJeeja KP int ret; 877c9b1e834SJeeja KP 878c9b1e834SJeeja KP dev_dbg(ctx->dev, "%s: pipe = %d\n", __func__, pipe->ppl_id); 879c9b1e834SJeeja KP 880c9b1e834SJeeja KP /* If pipe was not created in FW, do not try to pause or delete */ 881c9b1e834SJeeja KP if (pipe->state < SKL_PIPE_CREATED) 882c9b1e834SJeeja KP return 0; 883c9b1e834SJeeja KP 884c9b1e834SJeeja KP /* Pipe has to be paused before it is started */ 885c9b1e834SJeeja KP ret = skl_set_pipe_state(ctx, pipe, PPL_PAUSED); 886c9b1e834SJeeja KP if (ret < 0) { 887c9b1e834SJeeja KP dev_err(ctx->dev, "Failed to pause pipe\n"); 888c9b1e834SJeeja KP return ret; 889c9b1e834SJeeja KP } 890c9b1e834SJeeja KP 891c9b1e834SJeeja KP pipe->state = SKL_PIPE_PAUSED; 892c9b1e834SJeeja KP 893c9b1e834SJeeja KP ret = skl_set_pipe_state(ctx, pipe, PPL_RUNNING); 894c9b1e834SJeeja KP if (ret < 0) { 895c9b1e834SJeeja KP dev_err(ctx->dev, "Failed to start pipe\n"); 896c9b1e834SJeeja KP return ret; 897c9b1e834SJeeja KP } 898c9b1e834SJeeja KP 899c9b1e834SJeeja KP pipe->state = SKL_PIPE_STARTED; 900c9b1e834SJeeja KP 901c9b1e834SJeeja KP return 0; 902c9b1e834SJeeja KP } 903c9b1e834SJeeja KP 904c9b1e834SJeeja KP /* 905c9b1e834SJeeja KP * Stop the pipeline by sending set pipe state IPC 906c9b1e834SJeeja KP * DSP doesnt implement stop so we always send pause message 907c9b1e834SJeeja KP */ 908c9b1e834SJeeja KP int skl_stop_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) 909c9b1e834SJeeja KP { 910c9b1e834SJeeja KP int ret; 911c9b1e834SJeeja KP 912c9b1e834SJeeja KP dev_dbg(ctx->dev, "In %s pipe=%d\n", __func__, pipe->ppl_id); 913c9b1e834SJeeja KP 914c9b1e834SJeeja KP /* If pipe was not created in FW, do not try to pause or delete */ 915c9b1e834SJeeja KP if (pipe->state < SKL_PIPE_PAUSED) 916c9b1e834SJeeja KP return 0; 917c9b1e834SJeeja KP 918c9b1e834SJeeja KP ret = skl_set_pipe_state(ctx, pipe, PPL_PAUSED); 919c9b1e834SJeeja KP if (ret < 0) { 920c9b1e834SJeeja KP dev_dbg(ctx->dev, "Failed to stop pipe\n"); 921c9b1e834SJeeja KP return ret; 922c9b1e834SJeeja KP } 923c9b1e834SJeeja KP 924c9b1e834SJeeja KP pipe->state = SKL_PIPE_CREATED; 925c9b1e834SJeeja KP 926c9b1e834SJeeja KP return 0; 927c9b1e834SJeeja KP } 9289939a9c3SJeeja KP 9299939a9c3SJeeja KP /* Algo parameter set helper function */ 9309939a9c3SJeeja KP int skl_set_module_params(struct skl_sst *ctx, u32 *params, int size, 9319939a9c3SJeeja KP u32 param_id, struct skl_module_cfg *mcfg) 9329939a9c3SJeeja KP { 9339939a9c3SJeeja KP struct skl_ipc_large_config_msg msg; 9349939a9c3SJeeja KP 9359939a9c3SJeeja KP msg.module_id = mcfg->id.module_id; 9369939a9c3SJeeja KP msg.instance_id = mcfg->id.instance_id; 9379939a9c3SJeeja KP msg.param_data_size = size; 9389939a9c3SJeeja KP msg.large_param_id = param_id; 9399939a9c3SJeeja KP 9409939a9c3SJeeja KP return skl_ipc_set_large_config(&ctx->ipc, &msg, params); 9419939a9c3SJeeja KP } 9427d9f2911SOmair M Abdullah 9437d9f2911SOmair M Abdullah int skl_get_module_params(struct skl_sst *ctx, u32 *params, int size, 9447d9f2911SOmair M Abdullah u32 param_id, struct skl_module_cfg *mcfg) 9457d9f2911SOmair M Abdullah { 9467d9f2911SOmair M Abdullah struct skl_ipc_large_config_msg msg; 9477d9f2911SOmair M Abdullah 9487d9f2911SOmair M Abdullah msg.module_id = mcfg->id.module_id; 9497d9f2911SOmair M Abdullah msg.instance_id = mcfg->id.instance_id; 9507d9f2911SOmair M Abdullah msg.param_data_size = size; 9517d9f2911SOmair M Abdullah msg.large_param_id = param_id; 9527d9f2911SOmair M Abdullah 9537d9f2911SOmair M Abdullah return skl_ipc_get_large_config(&ctx->ipc, &msg, params); 9547d9f2911SOmair M Abdullah } 955