1e4e2d2f4SJeeja KP /* 2e4e2d2f4SJeeja KP * skl-topology.c - Implements Platform component ALSA controls/widget 3e4e2d2f4SJeeja KP * handlers. 4e4e2d2f4SJeeja KP * 5e4e2d2f4SJeeja KP * Copyright (C) 2014-2015 Intel Corp 6e4e2d2f4SJeeja KP * Author: Jeeja KP <jeeja.kp@intel.com> 7e4e2d2f4SJeeja KP * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 8e4e2d2f4SJeeja KP * 9e4e2d2f4SJeeja KP * This program is free software; you can redistribute it and/or modify 10e4e2d2f4SJeeja KP * it under the terms of the GNU General Public License as version 2, as 11e4e2d2f4SJeeja KP * published by the Free Software Foundation. 12e4e2d2f4SJeeja KP * 13e4e2d2f4SJeeja KP * This program is distributed in the hope that it will be useful, but 14e4e2d2f4SJeeja KP * WITHOUT ANY WARRANTY; without even the implied warranty of 15e4e2d2f4SJeeja KP * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16e4e2d2f4SJeeja KP * General Public License for more details. 17e4e2d2f4SJeeja KP */ 18e4e2d2f4SJeeja KP 19e4e2d2f4SJeeja KP #include <linux/slab.h> 20e4e2d2f4SJeeja KP #include <linux/types.h> 21e4e2d2f4SJeeja KP #include <linux/firmware.h> 22e4e2d2f4SJeeja KP #include <sound/soc.h> 23e4e2d2f4SJeeja KP #include <sound/soc-topology.h> 246277e832SShreyas NC #include <uapi/sound/snd_sst_tokens.h> 25e4e2d2f4SJeeja KP #include "skl-sst-dsp.h" 26e4e2d2f4SJeeja KP #include "skl-sst-ipc.h" 27e4e2d2f4SJeeja KP #include "skl-topology.h" 28e4e2d2f4SJeeja KP #include "skl.h" 29e4e2d2f4SJeeja KP #include "skl-tplg-interface.h" 306c5768b3SDharageswari R #include "../common/sst-dsp.h" 316c5768b3SDharageswari R #include "../common/sst-dsp-priv.h" 32e4e2d2f4SJeeja KP 33f7590d4fSJeeja KP #define SKL_CH_FIXUP_MASK (1 << 0) 34f7590d4fSJeeja KP #define SKL_RATE_FIXUP_MASK (1 << 1) 35f7590d4fSJeeja KP #define SKL_FMT_FIXUP_MASK (1 << 2) 366277e832SShreyas NC #define SKL_IN_DIR_BIT_MASK BIT(0) 376277e832SShreyas NC #define SKL_PIN_COUNT_MASK GENMASK(7, 4) 38f7590d4fSJeeja KP 39a83e3b4cSVinod Koul void skl_tplg_d0i3_get(struct skl *skl, enum d0i3_capability caps) 40a83e3b4cSVinod Koul { 41a83e3b4cSVinod Koul struct skl_d0i3_data *d0i3 = &skl->skl_sst->d0i3; 42a83e3b4cSVinod Koul 43a83e3b4cSVinod Koul switch (caps) { 44a83e3b4cSVinod Koul case SKL_D0I3_NONE: 45a83e3b4cSVinod Koul d0i3->non_d0i3++; 46a83e3b4cSVinod Koul break; 47a83e3b4cSVinod Koul 48a83e3b4cSVinod Koul case SKL_D0I3_STREAMING: 49a83e3b4cSVinod Koul d0i3->streaming++; 50a83e3b4cSVinod Koul break; 51a83e3b4cSVinod Koul 52a83e3b4cSVinod Koul case SKL_D0I3_NON_STREAMING: 53a83e3b4cSVinod Koul d0i3->non_streaming++; 54a83e3b4cSVinod Koul break; 55a83e3b4cSVinod Koul } 56a83e3b4cSVinod Koul } 57a83e3b4cSVinod Koul 58a83e3b4cSVinod Koul void skl_tplg_d0i3_put(struct skl *skl, enum d0i3_capability caps) 59a83e3b4cSVinod Koul { 60a83e3b4cSVinod Koul struct skl_d0i3_data *d0i3 = &skl->skl_sst->d0i3; 61a83e3b4cSVinod Koul 62a83e3b4cSVinod Koul switch (caps) { 63a83e3b4cSVinod Koul case SKL_D0I3_NONE: 64a83e3b4cSVinod Koul d0i3->non_d0i3--; 65a83e3b4cSVinod Koul break; 66a83e3b4cSVinod Koul 67a83e3b4cSVinod Koul case SKL_D0I3_STREAMING: 68a83e3b4cSVinod Koul d0i3->streaming--; 69a83e3b4cSVinod Koul break; 70a83e3b4cSVinod Koul 71a83e3b4cSVinod Koul case SKL_D0I3_NON_STREAMING: 72a83e3b4cSVinod Koul d0i3->non_streaming--; 73a83e3b4cSVinod Koul break; 74a83e3b4cSVinod Koul } 75a83e3b4cSVinod Koul } 76a83e3b4cSVinod Koul 77e4e2d2f4SJeeja KP /* 78e4e2d2f4SJeeja KP * SKL DSP driver modelling uses only few DAPM widgets so for rest we will 79e4e2d2f4SJeeja KP * ignore. This helpers checks if the SKL driver handles this widget type 80e4e2d2f4SJeeja KP */ 81e4e2d2f4SJeeja KP static int is_skl_dsp_widget_type(struct snd_soc_dapm_widget *w) 82e4e2d2f4SJeeja KP { 83e4e2d2f4SJeeja KP switch (w->id) { 84e4e2d2f4SJeeja KP case snd_soc_dapm_dai_link: 85e4e2d2f4SJeeja KP case snd_soc_dapm_dai_in: 86e4e2d2f4SJeeja KP case snd_soc_dapm_aif_in: 87e4e2d2f4SJeeja KP case snd_soc_dapm_aif_out: 88e4e2d2f4SJeeja KP case snd_soc_dapm_dai_out: 89e4e2d2f4SJeeja KP case snd_soc_dapm_switch: 90e4e2d2f4SJeeja KP return false; 91e4e2d2f4SJeeja KP default: 92e4e2d2f4SJeeja KP return true; 93e4e2d2f4SJeeja KP } 94e4e2d2f4SJeeja KP } 95e4e2d2f4SJeeja KP 96e4e2d2f4SJeeja KP /* 97e4e2d2f4SJeeja KP * Each pipelines needs memory to be allocated. Check if we have free memory 989ba8ffefSDharageswari.R * from available pool. 99e4e2d2f4SJeeja KP */ 1009ba8ffefSDharageswari.R static bool skl_is_pipe_mem_avail(struct skl *skl, 101e4e2d2f4SJeeja KP struct skl_module_cfg *mconfig) 102e4e2d2f4SJeeja KP { 103e4e2d2f4SJeeja KP struct skl_sst *ctx = skl->skl_sst; 104e4e2d2f4SJeeja KP 105e4e2d2f4SJeeja KP if (skl->resource.mem + mconfig->pipe->memory_pages > 106e4e2d2f4SJeeja KP skl->resource.max_mem) { 107e4e2d2f4SJeeja KP dev_err(ctx->dev, 108e4e2d2f4SJeeja KP "%s: module_id %d instance %d\n", __func__, 109e4e2d2f4SJeeja KP mconfig->id.module_id, 110e4e2d2f4SJeeja KP mconfig->id.instance_id); 111e4e2d2f4SJeeja KP dev_err(ctx->dev, 112e4e2d2f4SJeeja KP "exceeds ppl memory available %d mem %d\n", 113e4e2d2f4SJeeja KP skl->resource.max_mem, skl->resource.mem); 114e4e2d2f4SJeeja KP return false; 1159ba8ffefSDharageswari.R } else { 1169ba8ffefSDharageswari.R return true; 1179ba8ffefSDharageswari.R } 118e4e2d2f4SJeeja KP } 119e4e2d2f4SJeeja KP 1209ba8ffefSDharageswari.R /* 1219ba8ffefSDharageswari.R * Add the mem to the mem pool. This is freed when pipe is deleted. 1229ba8ffefSDharageswari.R * Note: DSP does actual memory management we only keep track for complete 1239ba8ffefSDharageswari.R * pool 1249ba8ffefSDharageswari.R */ 1259ba8ffefSDharageswari.R static void skl_tplg_alloc_pipe_mem(struct skl *skl, 1269ba8ffefSDharageswari.R struct skl_module_cfg *mconfig) 1279ba8ffefSDharageswari.R { 128e4e2d2f4SJeeja KP skl->resource.mem += mconfig->pipe->memory_pages; 129e4e2d2f4SJeeja KP } 130e4e2d2f4SJeeja KP 131e4e2d2f4SJeeja KP /* 132e4e2d2f4SJeeja KP * Pipeline needs needs DSP CPU resources for computation, this is 133e4e2d2f4SJeeja KP * quantified in MCPS (Million Clocks Per Second) required for module/pipe 134e4e2d2f4SJeeja KP * 135e4e2d2f4SJeeja KP * Each pipelines needs mcps to be allocated. Check if we have mcps for this 1369ba8ffefSDharageswari.R * pipe. 137e4e2d2f4SJeeja KP */ 1389ba8ffefSDharageswari.R 1399ba8ffefSDharageswari.R static bool skl_is_pipe_mcps_avail(struct skl *skl, 140e4e2d2f4SJeeja KP struct skl_module_cfg *mconfig) 141e4e2d2f4SJeeja KP { 142e4e2d2f4SJeeja KP struct skl_sst *ctx = skl->skl_sst; 143e4e2d2f4SJeeja KP 144e4e2d2f4SJeeja KP if (skl->resource.mcps + mconfig->mcps > skl->resource.max_mcps) { 145e4e2d2f4SJeeja KP dev_err(ctx->dev, 146e4e2d2f4SJeeja KP "%s: module_id %d instance %d\n", __func__, 147e4e2d2f4SJeeja KP mconfig->id.module_id, mconfig->id.instance_id); 148e4e2d2f4SJeeja KP dev_err(ctx->dev, 1497ca42f5aSGuneshwor Singh "exceeds ppl mcps available %d > mem %d\n", 150e4e2d2f4SJeeja KP skl->resource.max_mcps, skl->resource.mcps); 151e4e2d2f4SJeeja KP return false; 1529ba8ffefSDharageswari.R } else { 1539ba8ffefSDharageswari.R return true; 1549ba8ffefSDharageswari.R } 155e4e2d2f4SJeeja KP } 156e4e2d2f4SJeeja KP 1579ba8ffefSDharageswari.R static void skl_tplg_alloc_pipe_mcps(struct skl *skl, 1589ba8ffefSDharageswari.R struct skl_module_cfg *mconfig) 1599ba8ffefSDharageswari.R { 160e4e2d2f4SJeeja KP skl->resource.mcps += mconfig->mcps; 161e4e2d2f4SJeeja KP } 162e4e2d2f4SJeeja KP 163e4e2d2f4SJeeja KP /* 164e4e2d2f4SJeeja KP * Free the mcps when tearing down 165e4e2d2f4SJeeja KP */ 166e4e2d2f4SJeeja KP static void 167e4e2d2f4SJeeja KP skl_tplg_free_pipe_mcps(struct skl *skl, struct skl_module_cfg *mconfig) 168e4e2d2f4SJeeja KP { 169e4e2d2f4SJeeja KP skl->resource.mcps -= mconfig->mcps; 170e4e2d2f4SJeeja KP } 171e4e2d2f4SJeeja KP 172e4e2d2f4SJeeja KP /* 173e4e2d2f4SJeeja KP * Free the memory when tearing down 174e4e2d2f4SJeeja KP */ 175e4e2d2f4SJeeja KP static void 176e4e2d2f4SJeeja KP skl_tplg_free_pipe_mem(struct skl *skl, struct skl_module_cfg *mconfig) 177e4e2d2f4SJeeja KP { 178e4e2d2f4SJeeja KP skl->resource.mem -= mconfig->pipe->memory_pages; 179e4e2d2f4SJeeja KP } 180e4e2d2f4SJeeja KP 181f7590d4fSJeeja KP 182f7590d4fSJeeja KP static void skl_dump_mconfig(struct skl_sst *ctx, 183f7590d4fSJeeja KP struct skl_module_cfg *mcfg) 184f7590d4fSJeeja KP { 185f7590d4fSJeeja KP dev_dbg(ctx->dev, "Dumping config\n"); 186f7590d4fSJeeja KP dev_dbg(ctx->dev, "Input Format:\n"); 1874cd9899fSHardik T Shah dev_dbg(ctx->dev, "channels = %d\n", mcfg->in_fmt[0].channels); 1884cd9899fSHardik T Shah dev_dbg(ctx->dev, "s_freq = %d\n", mcfg->in_fmt[0].s_freq); 1894cd9899fSHardik T Shah dev_dbg(ctx->dev, "ch_cfg = %d\n", mcfg->in_fmt[0].ch_cfg); 1904cd9899fSHardik T Shah dev_dbg(ctx->dev, "valid bit depth = %d\n", mcfg->in_fmt[0].valid_bit_depth); 191f7590d4fSJeeja KP dev_dbg(ctx->dev, "Output Format:\n"); 1924cd9899fSHardik T Shah dev_dbg(ctx->dev, "channels = %d\n", mcfg->out_fmt[0].channels); 1934cd9899fSHardik T Shah dev_dbg(ctx->dev, "s_freq = %d\n", mcfg->out_fmt[0].s_freq); 1944cd9899fSHardik T Shah dev_dbg(ctx->dev, "valid bit depth = %d\n", mcfg->out_fmt[0].valid_bit_depth); 1954cd9899fSHardik T Shah dev_dbg(ctx->dev, "ch_cfg = %d\n", mcfg->out_fmt[0].ch_cfg); 196f7590d4fSJeeja KP } 197f7590d4fSJeeja KP 198ea5a137dSSubhransu S. Prusty static void skl_tplg_update_chmap(struct skl_module_fmt *fmt, int chs) 199ea5a137dSSubhransu S. Prusty { 200ea5a137dSSubhransu S. Prusty int slot_map = 0xFFFFFFFF; 201ea5a137dSSubhransu S. Prusty int start_slot = 0; 202ea5a137dSSubhransu S. Prusty int i; 203ea5a137dSSubhransu S. Prusty 204ea5a137dSSubhransu S. Prusty for (i = 0; i < chs; i++) { 205ea5a137dSSubhransu S. Prusty /* 206ea5a137dSSubhransu S. Prusty * For 2 channels with starting slot as 0, slot map will 207ea5a137dSSubhransu S. Prusty * look like 0xFFFFFF10. 208ea5a137dSSubhransu S. Prusty */ 209ea5a137dSSubhransu S. Prusty slot_map &= (~(0xF << (4 * i)) | (start_slot << (4 * i))); 210ea5a137dSSubhransu S. Prusty start_slot++; 211ea5a137dSSubhransu S. Prusty } 212ea5a137dSSubhransu S. Prusty fmt->ch_map = slot_map; 213ea5a137dSSubhransu S. Prusty } 214ea5a137dSSubhransu S. Prusty 215f7590d4fSJeeja KP static void skl_tplg_update_params(struct skl_module_fmt *fmt, 216f7590d4fSJeeja KP struct skl_pipe_params *params, int fixup) 217f7590d4fSJeeja KP { 218f7590d4fSJeeja KP if (fixup & SKL_RATE_FIXUP_MASK) 219f7590d4fSJeeja KP fmt->s_freq = params->s_freq; 220ea5a137dSSubhransu S. Prusty if (fixup & SKL_CH_FIXUP_MASK) { 221f7590d4fSJeeja KP fmt->channels = params->ch; 222ea5a137dSSubhransu S. Prusty skl_tplg_update_chmap(fmt, fmt->channels); 223ea5a137dSSubhransu S. Prusty } 22498256f83SJeeja KP if (fixup & SKL_FMT_FIXUP_MASK) { 22598256f83SJeeja KP fmt->valid_bit_depth = skl_get_bit_depth(params->s_fmt); 22698256f83SJeeja KP 22798256f83SJeeja KP /* 22898256f83SJeeja KP * 16 bit is 16 bit container whereas 24 bit is in 32 bit 22998256f83SJeeja KP * container so update bit depth accordingly 23098256f83SJeeja KP */ 23198256f83SJeeja KP switch (fmt->valid_bit_depth) { 23298256f83SJeeja KP case SKL_DEPTH_16BIT: 23398256f83SJeeja KP fmt->bit_depth = fmt->valid_bit_depth; 23498256f83SJeeja KP break; 23598256f83SJeeja KP 23698256f83SJeeja KP default: 23798256f83SJeeja KP fmt->bit_depth = SKL_DEPTH_32BIT; 23898256f83SJeeja KP break; 23998256f83SJeeja KP } 24098256f83SJeeja KP } 24198256f83SJeeja KP 242f7590d4fSJeeja KP } 243f7590d4fSJeeja KP 244f7590d4fSJeeja KP /* 245f7590d4fSJeeja KP * A pipeline may have modules which impact the pcm parameters, like SRC, 246f7590d4fSJeeja KP * channel converter, format converter. 247f7590d4fSJeeja KP * We need to calculate the output params by applying the 'fixup' 248f7590d4fSJeeja KP * Topology will tell driver which type of fixup is to be applied by 249f7590d4fSJeeja KP * supplying the fixup mask, so based on that we calculate the output 250f7590d4fSJeeja KP * 251f7590d4fSJeeja KP * Now In FE the pcm hw_params is source/target format. Same is applicable 252f7590d4fSJeeja KP * for BE with its hw_params invoked. 253f7590d4fSJeeja KP * here based on FE, BE pipeline and direction we calculate the input and 254f7590d4fSJeeja KP * outfix and then apply that for a module 255f7590d4fSJeeja KP */ 256f7590d4fSJeeja KP static void skl_tplg_update_params_fixup(struct skl_module_cfg *m_cfg, 257f7590d4fSJeeja KP struct skl_pipe_params *params, bool is_fe) 258f7590d4fSJeeja KP { 259f7590d4fSJeeja KP int in_fixup, out_fixup; 260f7590d4fSJeeja KP struct skl_module_fmt *in_fmt, *out_fmt; 261f7590d4fSJeeja KP 2624cd9899fSHardik T Shah /* Fixups will be applied to pin 0 only */ 2634cd9899fSHardik T Shah in_fmt = &m_cfg->in_fmt[0]; 2644cd9899fSHardik T Shah out_fmt = &m_cfg->out_fmt[0]; 265f7590d4fSJeeja KP 266f7590d4fSJeeja KP if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) { 267f7590d4fSJeeja KP if (is_fe) { 268f7590d4fSJeeja KP in_fixup = m_cfg->params_fixup; 269f7590d4fSJeeja KP out_fixup = (~m_cfg->converter) & 270f7590d4fSJeeja KP m_cfg->params_fixup; 271f7590d4fSJeeja KP } else { 272f7590d4fSJeeja KP out_fixup = m_cfg->params_fixup; 273f7590d4fSJeeja KP in_fixup = (~m_cfg->converter) & 274f7590d4fSJeeja KP m_cfg->params_fixup; 275f7590d4fSJeeja KP } 276f7590d4fSJeeja KP } else { 277f7590d4fSJeeja KP if (is_fe) { 278f7590d4fSJeeja KP out_fixup = m_cfg->params_fixup; 279f7590d4fSJeeja KP in_fixup = (~m_cfg->converter) & 280f7590d4fSJeeja KP m_cfg->params_fixup; 281f7590d4fSJeeja KP } else { 282f7590d4fSJeeja KP in_fixup = m_cfg->params_fixup; 283f7590d4fSJeeja KP out_fixup = (~m_cfg->converter) & 284f7590d4fSJeeja KP m_cfg->params_fixup; 285f7590d4fSJeeja KP } 286f7590d4fSJeeja KP } 287f7590d4fSJeeja KP 288f7590d4fSJeeja KP skl_tplg_update_params(in_fmt, params, in_fixup); 289f7590d4fSJeeja KP skl_tplg_update_params(out_fmt, params, out_fixup); 290f7590d4fSJeeja KP } 291f7590d4fSJeeja KP 292f7590d4fSJeeja KP /* 293f7590d4fSJeeja KP * A module needs input and output buffers, which are dependent upon pcm 294f7590d4fSJeeja KP * params, so once we have calculate params, we need buffer calculation as 295f7590d4fSJeeja KP * well. 296f7590d4fSJeeja KP */ 297f7590d4fSJeeja KP static void skl_tplg_update_buffer_size(struct skl_sst *ctx, 298f7590d4fSJeeja KP struct skl_module_cfg *mcfg) 299f7590d4fSJeeja KP { 300f7590d4fSJeeja KP int multiplier = 1; 3014cd9899fSHardik T Shah struct skl_module_fmt *in_fmt, *out_fmt; 3024cd9899fSHardik T Shah 3034cd9899fSHardik T Shah /* Since fixups is applied to pin 0 only, ibs, obs needs 3044cd9899fSHardik T Shah * change for pin 0 only 3054cd9899fSHardik T Shah */ 3064cd9899fSHardik T Shah in_fmt = &mcfg->in_fmt[0]; 3074cd9899fSHardik T Shah out_fmt = &mcfg->out_fmt[0]; 308f7590d4fSJeeja KP 309f7590d4fSJeeja KP if (mcfg->m_type == SKL_MODULE_TYPE_SRCINT) 310f7590d4fSJeeja KP multiplier = 5; 311f0c8e1d9SSubhransu S. Prusty 3128e15e762STakashi Sakamoto mcfg->ibs = DIV_ROUND_UP(in_fmt->s_freq, 1000) * 313998d6fb5STakashi Sakamoto in_fmt->channels * (in_fmt->bit_depth >> 3) * 314f7590d4fSJeeja KP multiplier; 315f7590d4fSJeeja KP 316998d6fb5STakashi Sakamoto mcfg->obs = DIV_ROUND_UP(out_fmt->s_freq, 1000) * 317998d6fb5STakashi Sakamoto out_fmt->channels * (out_fmt->bit_depth >> 3) * 318f7590d4fSJeeja KP multiplier; 319f7590d4fSJeeja KP } 320f7590d4fSJeeja KP 321db2f586bSSenthilnathan Veppur static u8 skl_tplg_be_dev_type(int dev_type) 322db2f586bSSenthilnathan Veppur { 323db2f586bSSenthilnathan Veppur int ret; 324db2f586bSSenthilnathan Veppur 325db2f586bSSenthilnathan Veppur switch (dev_type) { 326db2f586bSSenthilnathan Veppur case SKL_DEVICE_BT: 327db2f586bSSenthilnathan Veppur ret = NHLT_DEVICE_BT; 328db2f586bSSenthilnathan Veppur break; 329db2f586bSSenthilnathan Veppur 330db2f586bSSenthilnathan Veppur case SKL_DEVICE_DMIC: 331db2f586bSSenthilnathan Veppur ret = NHLT_DEVICE_DMIC; 332db2f586bSSenthilnathan Veppur break; 333db2f586bSSenthilnathan Veppur 334db2f586bSSenthilnathan Veppur case SKL_DEVICE_I2S: 335db2f586bSSenthilnathan Veppur ret = NHLT_DEVICE_I2S; 336db2f586bSSenthilnathan Veppur break; 337db2f586bSSenthilnathan Veppur 338db2f586bSSenthilnathan Veppur default: 339db2f586bSSenthilnathan Veppur ret = NHLT_DEVICE_INVALID; 340db2f586bSSenthilnathan Veppur break; 341db2f586bSSenthilnathan Veppur } 342db2f586bSSenthilnathan Veppur 343db2f586bSSenthilnathan Veppur return ret; 344db2f586bSSenthilnathan Veppur } 345db2f586bSSenthilnathan Veppur 3462d1419a3SJeeja KP static int skl_tplg_update_be_blob(struct snd_soc_dapm_widget *w, 3472d1419a3SJeeja KP struct skl_sst *ctx) 3482d1419a3SJeeja KP { 3492d1419a3SJeeja KP struct skl_module_cfg *m_cfg = w->priv; 3502d1419a3SJeeja KP int link_type, dir; 3512d1419a3SJeeja KP u32 ch, s_freq, s_fmt; 3522d1419a3SJeeja KP struct nhlt_specific_cfg *cfg; 3532d1419a3SJeeja KP struct skl *skl = get_skl_ctx(ctx->dev); 354db2f586bSSenthilnathan Veppur u8 dev_type = skl_tplg_be_dev_type(m_cfg->dev_type); 3552d1419a3SJeeja KP 3562d1419a3SJeeja KP /* check if we already have blob */ 3572d1419a3SJeeja KP if (m_cfg->formats_config.caps_size > 0) 3582d1419a3SJeeja KP return 0; 3592d1419a3SJeeja KP 360c7c6c736SJeeja KP dev_dbg(ctx->dev, "Applying default cfg blob\n"); 3612d1419a3SJeeja KP switch (m_cfg->dev_type) { 3622d1419a3SJeeja KP case SKL_DEVICE_DMIC: 3632d1419a3SJeeja KP link_type = NHLT_LINK_DMIC; 364c7c6c736SJeeja KP dir = SNDRV_PCM_STREAM_CAPTURE; 3652d1419a3SJeeja KP s_freq = m_cfg->in_fmt[0].s_freq; 3662d1419a3SJeeja KP s_fmt = m_cfg->in_fmt[0].bit_depth; 3672d1419a3SJeeja KP ch = m_cfg->in_fmt[0].channels; 3682d1419a3SJeeja KP break; 3692d1419a3SJeeja KP 3702d1419a3SJeeja KP case SKL_DEVICE_I2S: 3712d1419a3SJeeja KP link_type = NHLT_LINK_SSP; 3722d1419a3SJeeja KP if (m_cfg->hw_conn_type == SKL_CONN_SOURCE) { 373c7c6c736SJeeja KP dir = SNDRV_PCM_STREAM_PLAYBACK; 3742d1419a3SJeeja KP s_freq = m_cfg->out_fmt[0].s_freq; 3752d1419a3SJeeja KP s_fmt = m_cfg->out_fmt[0].bit_depth; 3762d1419a3SJeeja KP ch = m_cfg->out_fmt[0].channels; 377c7c6c736SJeeja KP } else { 378c7c6c736SJeeja KP dir = SNDRV_PCM_STREAM_CAPTURE; 379c7c6c736SJeeja KP s_freq = m_cfg->in_fmt[0].s_freq; 380c7c6c736SJeeja KP s_fmt = m_cfg->in_fmt[0].bit_depth; 381c7c6c736SJeeja KP ch = m_cfg->in_fmt[0].channels; 3822d1419a3SJeeja KP } 3832d1419a3SJeeja KP break; 3842d1419a3SJeeja KP 3852d1419a3SJeeja KP default: 3862d1419a3SJeeja KP return -EINVAL; 3872d1419a3SJeeja KP } 3882d1419a3SJeeja KP 3892d1419a3SJeeja KP /* update the blob based on virtual bus_id and default params */ 3902d1419a3SJeeja KP cfg = skl_get_ep_blob(skl, m_cfg->vbus_id, link_type, 391db2f586bSSenthilnathan Veppur s_fmt, ch, s_freq, dir, dev_type); 3922d1419a3SJeeja KP if (cfg) { 3932d1419a3SJeeja KP m_cfg->formats_config.caps_size = cfg->size; 3942d1419a3SJeeja KP m_cfg->formats_config.caps = (u32 *) &cfg->caps; 3952d1419a3SJeeja KP } else { 3962d1419a3SJeeja KP dev_err(ctx->dev, "Blob NULL for id %x type %d dirn %d\n", 3972d1419a3SJeeja KP m_cfg->vbus_id, link_type, dir); 3982d1419a3SJeeja KP dev_err(ctx->dev, "PCM: ch %d, freq %d, fmt %d\n", 3992d1419a3SJeeja KP ch, s_freq, s_fmt); 4002d1419a3SJeeja KP return -EIO; 4012d1419a3SJeeja KP } 4022d1419a3SJeeja KP 4032d1419a3SJeeja KP return 0; 4042d1419a3SJeeja KP } 4052d1419a3SJeeja KP 406f7590d4fSJeeja KP static void skl_tplg_update_module_params(struct snd_soc_dapm_widget *w, 407f7590d4fSJeeja KP struct skl_sst *ctx) 408f7590d4fSJeeja KP { 409f7590d4fSJeeja KP struct skl_module_cfg *m_cfg = w->priv; 410f7590d4fSJeeja KP struct skl_pipe_params *params = m_cfg->pipe->p_params; 411f7590d4fSJeeja KP int p_conn_type = m_cfg->pipe->conn_type; 412f7590d4fSJeeja KP bool is_fe; 413f7590d4fSJeeja KP 414f7590d4fSJeeja KP if (!m_cfg->params_fixup) 415f7590d4fSJeeja KP return; 416f7590d4fSJeeja KP 417f7590d4fSJeeja KP dev_dbg(ctx->dev, "Mconfig for widget=%s BEFORE updation\n", 418f7590d4fSJeeja KP w->name); 419f7590d4fSJeeja KP 420f7590d4fSJeeja KP skl_dump_mconfig(ctx, m_cfg); 421f7590d4fSJeeja KP 422f7590d4fSJeeja KP if (p_conn_type == SKL_PIPE_CONN_TYPE_FE) 423f7590d4fSJeeja KP is_fe = true; 424f7590d4fSJeeja KP else 425f7590d4fSJeeja KP is_fe = false; 426f7590d4fSJeeja KP 427f7590d4fSJeeja KP skl_tplg_update_params_fixup(m_cfg, params, is_fe); 428f7590d4fSJeeja KP skl_tplg_update_buffer_size(ctx, m_cfg); 429f7590d4fSJeeja KP 430f7590d4fSJeeja KP dev_dbg(ctx->dev, "Mconfig for widget=%s AFTER updation\n", 431f7590d4fSJeeja KP w->name); 432f7590d4fSJeeja KP 433f7590d4fSJeeja KP skl_dump_mconfig(ctx, m_cfg); 434f7590d4fSJeeja KP } 435f7590d4fSJeeja KP 436e4e2d2f4SJeeja KP /* 437abb74003SJeeja KP * some modules can have multiple params set from user control and 438abb74003SJeeja KP * need to be set after module is initialized. If set_param flag is 439abb74003SJeeja KP * set module params will be done after module is initialised. 440abb74003SJeeja KP */ 441abb74003SJeeja KP static int skl_tplg_set_module_params(struct snd_soc_dapm_widget *w, 442abb74003SJeeja KP struct skl_sst *ctx) 443abb74003SJeeja KP { 444abb74003SJeeja KP int i, ret; 445abb74003SJeeja KP struct skl_module_cfg *mconfig = w->priv; 446abb74003SJeeja KP const struct snd_kcontrol_new *k; 447abb74003SJeeja KP struct soc_bytes_ext *sb; 448abb74003SJeeja KP struct skl_algo_data *bc; 449abb74003SJeeja KP struct skl_specific_cfg *sp_cfg; 450abb74003SJeeja KP 451abb74003SJeeja KP if (mconfig->formats_config.caps_size > 0 && 4524ced1827SJeeja KP mconfig->formats_config.set_params == SKL_PARAM_SET) { 453abb74003SJeeja KP sp_cfg = &mconfig->formats_config; 454abb74003SJeeja KP ret = skl_set_module_params(ctx, sp_cfg->caps, 455abb74003SJeeja KP sp_cfg->caps_size, 456abb74003SJeeja KP sp_cfg->param_id, mconfig); 457abb74003SJeeja KP if (ret < 0) 458abb74003SJeeja KP return ret; 459abb74003SJeeja KP } 460abb74003SJeeja KP 461abb74003SJeeja KP for (i = 0; i < w->num_kcontrols; i++) { 462abb74003SJeeja KP k = &w->kcontrol_news[i]; 463abb74003SJeeja KP if (k->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { 464abb74003SJeeja KP sb = (void *) k->private_value; 465abb74003SJeeja KP bc = (struct skl_algo_data *)sb->dobj.private; 466abb74003SJeeja KP 4674ced1827SJeeja KP if (bc->set_params == SKL_PARAM_SET) { 468abb74003SJeeja KP ret = skl_set_module_params(ctx, 4690d682104SDharageswari R (u32 *)bc->params, bc->size, 470abb74003SJeeja KP bc->param_id, mconfig); 471abb74003SJeeja KP if (ret < 0) 472abb74003SJeeja KP return ret; 473abb74003SJeeja KP } 474abb74003SJeeja KP } 475abb74003SJeeja KP } 476abb74003SJeeja KP 477abb74003SJeeja KP return 0; 478abb74003SJeeja KP } 479abb74003SJeeja KP 480abb74003SJeeja KP /* 481abb74003SJeeja KP * some module param can set from user control and this is required as 482abb74003SJeeja KP * when module is initailzed. if module param is required in init it is 483abb74003SJeeja KP * identifed by set_param flag. if set_param flag is not set, then this 484abb74003SJeeja KP * parameter needs to set as part of module init. 485abb74003SJeeja KP */ 486abb74003SJeeja KP static int skl_tplg_set_module_init_data(struct snd_soc_dapm_widget *w) 487abb74003SJeeja KP { 488abb74003SJeeja KP const struct snd_kcontrol_new *k; 489abb74003SJeeja KP struct soc_bytes_ext *sb; 490abb74003SJeeja KP struct skl_algo_data *bc; 491abb74003SJeeja KP struct skl_module_cfg *mconfig = w->priv; 492abb74003SJeeja KP int i; 493abb74003SJeeja KP 494abb74003SJeeja KP for (i = 0; i < w->num_kcontrols; i++) { 495abb74003SJeeja KP k = &w->kcontrol_news[i]; 496abb74003SJeeja KP if (k->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { 497abb74003SJeeja KP sb = (struct soc_bytes_ext *)k->private_value; 498abb74003SJeeja KP bc = (struct skl_algo_data *)sb->dobj.private; 499abb74003SJeeja KP 5004ced1827SJeeja KP if (bc->set_params != SKL_PARAM_INIT) 501abb74003SJeeja KP continue; 502abb74003SJeeja KP 503abb74003SJeeja KP mconfig->formats_config.caps = (u32 *)&bc->params; 5040d682104SDharageswari R mconfig->formats_config.caps_size = bc->size; 505abb74003SJeeja KP 506abb74003SJeeja KP break; 507abb74003SJeeja KP } 508abb74003SJeeja KP } 509abb74003SJeeja KP 510abb74003SJeeja KP return 0; 511abb74003SJeeja KP } 512abb74003SJeeja KP 513bb704a73SJeeja KP static int skl_tplg_module_prepare(struct skl_sst *ctx, struct skl_pipe *pipe, 514bb704a73SJeeja KP struct snd_soc_dapm_widget *w, struct skl_module_cfg *mcfg) 515bb704a73SJeeja KP { 516bb704a73SJeeja KP switch (mcfg->dev_type) { 517bb704a73SJeeja KP case SKL_DEVICE_HDAHOST: 518bb704a73SJeeja KP return skl_pcm_host_dma_prepare(ctx->dev, pipe->p_params); 519bb704a73SJeeja KP 520bb704a73SJeeja KP case SKL_DEVICE_HDALINK: 521bb704a73SJeeja KP return skl_pcm_link_dma_prepare(ctx->dev, pipe->p_params); 522bb704a73SJeeja KP } 523bb704a73SJeeja KP 524bb704a73SJeeja KP return 0; 525bb704a73SJeeja KP } 526bb704a73SJeeja KP 527abb74003SJeeja KP /* 528e4e2d2f4SJeeja KP * Inside a pipe instance, we can have various modules. These modules need 529e4e2d2f4SJeeja KP * to instantiated in DSP by invoking INIT_MODULE IPC, which is achieved by 530e4e2d2f4SJeeja KP * skl_init_module() routine, so invoke that for all modules in a pipeline 531e4e2d2f4SJeeja KP */ 532e4e2d2f4SJeeja KP static int 533e4e2d2f4SJeeja KP skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe) 534e4e2d2f4SJeeja KP { 535e4e2d2f4SJeeja KP struct skl_pipe_module *w_module; 536e4e2d2f4SJeeja KP struct snd_soc_dapm_widget *w; 537e4e2d2f4SJeeja KP struct skl_module_cfg *mconfig; 538e4e2d2f4SJeeja KP struct skl_sst *ctx = skl->skl_sst; 539e4e2d2f4SJeeja KP int ret = 0; 540e4e2d2f4SJeeja KP 541e4e2d2f4SJeeja KP list_for_each_entry(w_module, &pipe->w_list, node) { 542b26199eaSJeeja KP uuid_le *uuid_mod; 543e4e2d2f4SJeeja KP w = w_module->w; 544e4e2d2f4SJeeja KP mconfig = w->priv; 545e4e2d2f4SJeeja KP 546b7c50555SVinod Koul /* check if module ids are populated */ 547b7c50555SVinod Koul if (mconfig->id.module_id < 0) { 548b7c50555SVinod Koul dev_err(skl->skl_sst->dev, 549a657ae7eSVinod Koul "module %pUL id not populated\n", 550a657ae7eSVinod Koul (uuid_le *)mconfig->guid); 551a657ae7eSVinod Koul return -EIO; 552b7c50555SVinod Koul } 553b7c50555SVinod Koul 554e4e2d2f4SJeeja KP /* check resource available */ 5559ba8ffefSDharageswari.R if (!skl_is_pipe_mcps_avail(skl, mconfig)) 556e4e2d2f4SJeeja KP return -ENOMEM; 557e4e2d2f4SJeeja KP 5586c5768b3SDharageswari R if (mconfig->is_loadable && ctx->dsp->fw_ops.load_mod) { 5596c5768b3SDharageswari R ret = ctx->dsp->fw_ops.load_mod(ctx->dsp, 5606c5768b3SDharageswari R mconfig->id.module_id, mconfig->guid); 5616c5768b3SDharageswari R if (ret < 0) 5626c5768b3SDharageswari R return ret; 563d643678bSJeeja KP 564d643678bSJeeja KP mconfig->m_state = SKL_MODULE_LOADED; 5656c5768b3SDharageswari R } 5666c5768b3SDharageswari R 567bb704a73SJeeja KP /* prepare the DMA if the module is gateway cpr */ 568bb704a73SJeeja KP ret = skl_tplg_module_prepare(ctx, pipe, w, mconfig); 569bb704a73SJeeja KP if (ret < 0) 570bb704a73SJeeja KP return ret; 571bb704a73SJeeja KP 5722d1419a3SJeeja KP /* update blob if blob is null for be with default value */ 5732d1419a3SJeeja KP skl_tplg_update_be_blob(w, ctx); 5742d1419a3SJeeja KP 575f7590d4fSJeeja KP /* 576f7590d4fSJeeja KP * apply fix/conversion to module params based on 577f7590d4fSJeeja KP * FE/BE params 578f7590d4fSJeeja KP */ 579f7590d4fSJeeja KP skl_tplg_update_module_params(w, ctx); 580b26199eaSJeeja KP uuid_mod = (uuid_le *)mconfig->guid; 581b26199eaSJeeja KP mconfig->id.pvt_id = skl_get_pvt_id(ctx, uuid_mod, 582b26199eaSJeeja KP mconfig->id.instance_id); 583ef2a352cSDharageswari R if (mconfig->id.pvt_id < 0) 584ef2a352cSDharageswari R return ret; 585abb74003SJeeja KP skl_tplg_set_module_init_data(w); 5869939a9c3SJeeja KP ret = skl_init_module(ctx, mconfig); 587ef2a352cSDharageswari R if (ret < 0) { 588b26199eaSJeeja KP skl_put_pvt_id(ctx, uuid_mod, &mconfig->id.pvt_id); 589e4e2d2f4SJeeja KP return ret; 590ef2a352cSDharageswari R } 591260eb73aSDharageswari R skl_tplg_alloc_pipe_mcps(skl, mconfig); 592abb74003SJeeja KP ret = skl_tplg_set_module_params(w, ctx); 593e4e2d2f4SJeeja KP if (ret < 0) 594e4e2d2f4SJeeja KP return ret; 595e4e2d2f4SJeeja KP } 596e4e2d2f4SJeeja KP 597e4e2d2f4SJeeja KP return 0; 598e4e2d2f4SJeeja KP } 599d93f8e55SVinod Koul 6006c5768b3SDharageswari R static int skl_tplg_unload_pipe_modules(struct skl_sst *ctx, 6016c5768b3SDharageswari R struct skl_pipe *pipe) 6026c5768b3SDharageswari R { 603b0fab9c6SDharageswari R int ret; 6046c5768b3SDharageswari R struct skl_pipe_module *w_module = NULL; 6056c5768b3SDharageswari R struct skl_module_cfg *mconfig = NULL; 6066c5768b3SDharageswari R 6076c5768b3SDharageswari R list_for_each_entry(w_module, &pipe->w_list, node) { 608b26199eaSJeeja KP uuid_le *uuid_mod; 6096c5768b3SDharageswari R mconfig = w_module->w->priv; 610b26199eaSJeeja KP uuid_mod = (uuid_le *)mconfig->guid; 6116c5768b3SDharageswari R 612d643678bSJeeja KP if (mconfig->is_loadable && ctx->dsp->fw_ops.unload_mod && 613b0fab9c6SDharageswari R mconfig->m_state > SKL_MODULE_UNINIT) { 614b0fab9c6SDharageswari R ret = ctx->dsp->fw_ops.unload_mod(ctx->dsp, 6156c5768b3SDharageswari R mconfig->id.module_id); 616b0fab9c6SDharageswari R if (ret < 0) 617b0fab9c6SDharageswari R return -EIO; 618b0fab9c6SDharageswari R } 619b26199eaSJeeja KP skl_put_pvt_id(ctx, uuid_mod, &mconfig->id.pvt_id); 6206c5768b3SDharageswari R } 6216c5768b3SDharageswari R 6226c5768b3SDharageswari R /* no modules to unload in this path, so return */ 6236c5768b3SDharageswari R return 0; 6246c5768b3SDharageswari R } 6256c5768b3SDharageswari R 626d93f8e55SVinod Koul /* 627d93f8e55SVinod Koul * Mixer module represents a pipeline. So in the Pre-PMU event of mixer we 628d93f8e55SVinod Koul * need create the pipeline. So we do following: 629d93f8e55SVinod Koul * - check the resources 630d93f8e55SVinod Koul * - Create the pipeline 631d93f8e55SVinod Koul * - Initialize the modules in pipeline 632d93f8e55SVinod Koul * - finally bind all modules together 633d93f8e55SVinod Koul */ 634d93f8e55SVinod Koul static int skl_tplg_mixer_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w, 635d93f8e55SVinod Koul struct skl *skl) 636d93f8e55SVinod Koul { 637d93f8e55SVinod Koul int ret; 638d93f8e55SVinod Koul struct skl_module_cfg *mconfig = w->priv; 639d93f8e55SVinod Koul struct skl_pipe_module *w_module; 640d93f8e55SVinod Koul struct skl_pipe *s_pipe = mconfig->pipe; 641b8c722ddSJeeja KP struct skl_module_cfg *src_module = NULL, *dst_module, *module; 642d93f8e55SVinod Koul struct skl_sst *ctx = skl->skl_sst; 643b8c722ddSJeeja KP struct skl_module_deferred_bind *modules; 644d93f8e55SVinod Koul 645d93f8e55SVinod Koul /* check resource available */ 6469ba8ffefSDharageswari.R if (!skl_is_pipe_mcps_avail(skl, mconfig)) 647d93f8e55SVinod Koul return -EBUSY; 648d93f8e55SVinod Koul 6499ba8ffefSDharageswari.R if (!skl_is_pipe_mem_avail(skl, mconfig)) 650d93f8e55SVinod Koul return -ENOMEM; 651d93f8e55SVinod Koul 652d93f8e55SVinod Koul /* 653d93f8e55SVinod Koul * Create a list of modules for pipe. 654d93f8e55SVinod Koul * This list contains modules from source to sink 655d93f8e55SVinod Koul */ 656d93f8e55SVinod Koul ret = skl_create_pipeline(ctx, mconfig->pipe); 657d93f8e55SVinod Koul if (ret < 0) 658d93f8e55SVinod Koul return ret; 659d93f8e55SVinod Koul 660260eb73aSDharageswari R skl_tplg_alloc_pipe_mem(skl, mconfig); 661260eb73aSDharageswari R skl_tplg_alloc_pipe_mcps(skl, mconfig); 662d93f8e55SVinod Koul 663d93f8e55SVinod Koul /* Init all pipe modules from source to sink */ 664d93f8e55SVinod Koul ret = skl_tplg_init_pipe_modules(skl, s_pipe); 665d93f8e55SVinod Koul if (ret < 0) 666d93f8e55SVinod Koul return ret; 667d93f8e55SVinod Koul 668d93f8e55SVinod Koul /* Bind modules from source to sink */ 669d93f8e55SVinod Koul list_for_each_entry(w_module, &s_pipe->w_list, node) { 670d93f8e55SVinod Koul dst_module = w_module->w->priv; 671d93f8e55SVinod Koul 672d93f8e55SVinod Koul if (src_module == NULL) { 673d93f8e55SVinod Koul src_module = dst_module; 674d93f8e55SVinod Koul continue; 675d93f8e55SVinod Koul } 676d93f8e55SVinod Koul 677d93f8e55SVinod Koul ret = skl_bind_modules(ctx, src_module, dst_module); 678d93f8e55SVinod Koul if (ret < 0) 679d93f8e55SVinod Koul return ret; 680d93f8e55SVinod Koul 681d93f8e55SVinod Koul src_module = dst_module; 682d93f8e55SVinod Koul } 683d93f8e55SVinod Koul 684b8c722ddSJeeja KP /* 685b8c722ddSJeeja KP * When the destination module is initialized, check for these modules 686b8c722ddSJeeja KP * in deferred bind list. If found, bind them. 687b8c722ddSJeeja KP */ 688b8c722ddSJeeja KP list_for_each_entry(w_module, &s_pipe->w_list, node) { 689b8c722ddSJeeja KP if (list_empty(&skl->bind_list)) 690b8c722ddSJeeja KP break; 691b8c722ddSJeeja KP 692b8c722ddSJeeja KP list_for_each_entry(modules, &skl->bind_list, node) { 693b8c722ddSJeeja KP module = w_module->w->priv; 694b8c722ddSJeeja KP if (modules->dst == module) 695b8c722ddSJeeja KP skl_bind_modules(ctx, modules->src, 696b8c722ddSJeeja KP modules->dst); 697b8c722ddSJeeja KP } 698b8c722ddSJeeja KP } 699b8c722ddSJeeja KP 700d93f8e55SVinod Koul return 0; 701d93f8e55SVinod Koul } 702d93f8e55SVinod Koul 703bf3e5ef5SDharageswari R static int skl_fill_sink_instance_id(struct skl_sst *ctx, u32 *params, 704bf3e5ef5SDharageswari R int size, struct skl_module_cfg *mcfg) 7055e8f0ee4SDharageswari R { 7065e8f0ee4SDharageswari R int i, pvt_id; 7075e8f0ee4SDharageswari R 708bf3e5ef5SDharageswari R if (mcfg->m_type == SKL_MODULE_TYPE_KPB) { 709bf3e5ef5SDharageswari R struct skl_kpb_params *kpb_params = 710bf3e5ef5SDharageswari R (struct skl_kpb_params *)params; 711bf3e5ef5SDharageswari R struct skl_mod_inst_map *inst = kpb_params->map; 7125e8f0ee4SDharageswari R 713bf3e5ef5SDharageswari R for (i = 0; i < kpb_params->num_modules; i++) { 714bf3e5ef5SDharageswari R pvt_id = skl_get_pvt_instance_id_map(ctx, inst->mod_id, 715bf3e5ef5SDharageswari R inst->inst_id); 7165e8f0ee4SDharageswari R if (pvt_id < 0) 7175e8f0ee4SDharageswari R return -EINVAL; 718bf3e5ef5SDharageswari R 7195e8f0ee4SDharageswari R inst->inst_id = pvt_id; 7205e8f0ee4SDharageswari R inst++; 7215e8f0ee4SDharageswari R } 7225e8f0ee4SDharageswari R } 7235e8f0ee4SDharageswari R 724bf3e5ef5SDharageswari R return 0; 725bf3e5ef5SDharageswari R } 726cc6a4044SJeeja KP /* 727cc6a4044SJeeja KP * Some modules require params to be set after the module is bound to 728cc6a4044SJeeja KP * all pins connected. 729cc6a4044SJeeja KP * 730cc6a4044SJeeja KP * The module provider initializes set_param flag for such modules and we 731cc6a4044SJeeja KP * send params after binding 732cc6a4044SJeeja KP */ 733cc6a4044SJeeja KP static int skl_tplg_set_module_bind_params(struct snd_soc_dapm_widget *w, 734cc6a4044SJeeja KP struct skl_module_cfg *mcfg, struct skl_sst *ctx) 735cc6a4044SJeeja KP { 736cc6a4044SJeeja KP int i, ret; 737cc6a4044SJeeja KP struct skl_module_cfg *mconfig = w->priv; 738cc6a4044SJeeja KP const struct snd_kcontrol_new *k; 739cc6a4044SJeeja KP struct soc_bytes_ext *sb; 740cc6a4044SJeeja KP struct skl_algo_data *bc; 741cc6a4044SJeeja KP struct skl_specific_cfg *sp_cfg; 742bf3e5ef5SDharageswari R u32 *params; 743cc6a4044SJeeja KP 744cc6a4044SJeeja KP /* 745cc6a4044SJeeja KP * check all out/in pins are in bind state. 746cc6a4044SJeeja KP * if so set the module param 747cc6a4044SJeeja KP */ 748cc6a4044SJeeja KP for (i = 0; i < mcfg->max_out_queue; i++) { 749cc6a4044SJeeja KP if (mcfg->m_out_pin[i].pin_state != SKL_PIN_BIND_DONE) 750cc6a4044SJeeja KP return 0; 751cc6a4044SJeeja KP } 752cc6a4044SJeeja KP 753cc6a4044SJeeja KP for (i = 0; i < mcfg->max_in_queue; i++) { 754cc6a4044SJeeja KP if (mcfg->m_in_pin[i].pin_state != SKL_PIN_BIND_DONE) 755cc6a4044SJeeja KP return 0; 756cc6a4044SJeeja KP } 757cc6a4044SJeeja KP 758cc6a4044SJeeja KP if (mconfig->formats_config.caps_size > 0 && 759cc6a4044SJeeja KP mconfig->formats_config.set_params == SKL_PARAM_BIND) { 760cc6a4044SJeeja KP sp_cfg = &mconfig->formats_config; 761cc6a4044SJeeja KP ret = skl_set_module_params(ctx, sp_cfg->caps, 762cc6a4044SJeeja KP sp_cfg->caps_size, 763cc6a4044SJeeja KP sp_cfg->param_id, mconfig); 764cc6a4044SJeeja KP if (ret < 0) 765cc6a4044SJeeja KP return ret; 766cc6a4044SJeeja KP } 767cc6a4044SJeeja KP 768cc6a4044SJeeja KP for (i = 0; i < w->num_kcontrols; i++) { 769cc6a4044SJeeja KP k = &w->kcontrol_news[i]; 770cc6a4044SJeeja KP if (k->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { 771cc6a4044SJeeja KP sb = (void *) k->private_value; 772cc6a4044SJeeja KP bc = (struct skl_algo_data *)sb->dobj.private; 773cc6a4044SJeeja KP 774cc6a4044SJeeja KP if (bc->set_params == SKL_PARAM_BIND) { 775bf3e5ef5SDharageswari R params = kzalloc(bc->max, GFP_KERNEL); 776bf3e5ef5SDharageswari R if (!params) 777bf3e5ef5SDharageswari R return -ENOMEM; 778bf3e5ef5SDharageswari R 779bf3e5ef5SDharageswari R memcpy(params, bc->params, bc->max); 780bf3e5ef5SDharageswari R skl_fill_sink_instance_id(ctx, params, bc->max, 781bf3e5ef5SDharageswari R mconfig); 782bf3e5ef5SDharageswari R 783bf3e5ef5SDharageswari R ret = skl_set_module_params(ctx, params, 784bf3e5ef5SDharageswari R bc->max, bc->param_id, mconfig); 785bf3e5ef5SDharageswari R kfree(params); 786bf3e5ef5SDharageswari R 787cc6a4044SJeeja KP if (ret < 0) 788cc6a4044SJeeja KP return ret; 789cc6a4044SJeeja KP } 790cc6a4044SJeeja KP } 791cc6a4044SJeeja KP } 792cc6a4044SJeeja KP 793cc6a4044SJeeja KP return 0; 794cc6a4044SJeeja KP } 795cc6a4044SJeeja KP 796b8c722ddSJeeja KP 797b8c722ddSJeeja KP static int skl_tplg_module_add_deferred_bind(struct skl *skl, 798b8c722ddSJeeja KP struct skl_module_cfg *src, struct skl_module_cfg *dst) 799b8c722ddSJeeja KP { 800b8c722ddSJeeja KP struct skl_module_deferred_bind *m_list, *modules; 801b8c722ddSJeeja KP int i; 802b8c722ddSJeeja KP 803b8c722ddSJeeja KP /* only supported for module with static pin connection */ 804b8c722ddSJeeja KP for (i = 0; i < dst->max_in_queue; i++) { 805b8c722ddSJeeja KP struct skl_module_pin *pin = &dst->m_in_pin[i]; 806b8c722ddSJeeja KP 807b8c722ddSJeeja KP if (pin->is_dynamic) 808b8c722ddSJeeja KP continue; 809b8c722ddSJeeja KP 810b8c722ddSJeeja KP if ((pin->id.module_id == src->id.module_id) && 811b8c722ddSJeeja KP (pin->id.instance_id == src->id.instance_id)) { 812b8c722ddSJeeja KP 813b8c722ddSJeeja KP if (!list_empty(&skl->bind_list)) { 814b8c722ddSJeeja KP list_for_each_entry(modules, &skl->bind_list, node) { 815b8c722ddSJeeja KP if (modules->src == src && modules->dst == dst) 816b8c722ddSJeeja KP return 0; 817b8c722ddSJeeja KP } 818b8c722ddSJeeja KP } 819b8c722ddSJeeja KP 820b8c722ddSJeeja KP m_list = kzalloc(sizeof(*m_list), GFP_KERNEL); 821b8c722ddSJeeja KP if (!m_list) 822b8c722ddSJeeja KP return -ENOMEM; 823b8c722ddSJeeja KP 824b8c722ddSJeeja KP m_list->src = src; 825b8c722ddSJeeja KP m_list->dst = dst; 826b8c722ddSJeeja KP 827b8c722ddSJeeja KP list_add(&m_list->node, &skl->bind_list); 828b8c722ddSJeeja KP } 829b8c722ddSJeeja KP } 830b8c722ddSJeeja KP 831b8c722ddSJeeja KP return 0; 832b8c722ddSJeeja KP } 833b8c722ddSJeeja KP 8348724ff17SJeeja KP static int skl_tplg_bind_sinks(struct snd_soc_dapm_widget *w, 8358724ff17SJeeja KP struct skl *skl, 8366bd4cf85SJeeja KP struct snd_soc_dapm_widget *src_w, 8378724ff17SJeeja KP struct skl_module_cfg *src_mconfig) 838d93f8e55SVinod Koul { 839d93f8e55SVinod Koul struct snd_soc_dapm_path *p; 8400ed95d76SJeeja KP struct snd_soc_dapm_widget *sink = NULL, *next_sink = NULL; 8418724ff17SJeeja KP struct skl_module_cfg *sink_mconfig; 842d93f8e55SVinod Koul struct skl_sst *ctx = skl->skl_sst; 8438724ff17SJeeja KP int ret; 844d93f8e55SVinod Koul 8458724ff17SJeeja KP snd_soc_dapm_widget_for_each_sink_path(w, p) { 846d93f8e55SVinod Koul if (!p->connect) 847d93f8e55SVinod Koul continue; 848d93f8e55SVinod Koul 849d93f8e55SVinod Koul dev_dbg(ctx->dev, "%s: src widget=%s\n", __func__, w->name); 850d93f8e55SVinod Koul dev_dbg(ctx->dev, "%s: sink widget=%s\n", __func__, p->sink->name); 851d93f8e55SVinod Koul 8520ed95d76SJeeja KP next_sink = p->sink; 8536bd4cf85SJeeja KP 8546bd4cf85SJeeja KP if (!is_skl_dsp_widget_type(p->sink)) 8556bd4cf85SJeeja KP return skl_tplg_bind_sinks(p->sink, skl, src_w, src_mconfig); 8566bd4cf85SJeeja KP 857d93f8e55SVinod Koul /* 858d93f8e55SVinod Koul * here we will check widgets in sink pipelines, so that 859d93f8e55SVinod Koul * can be any widgets type and we are only interested if 860d93f8e55SVinod Koul * they are ones used for SKL so check that first 861d93f8e55SVinod Koul */ 862d93f8e55SVinod Koul if ((p->sink->priv != NULL) && 863d93f8e55SVinod Koul is_skl_dsp_widget_type(p->sink)) { 864d93f8e55SVinod Koul 865d93f8e55SVinod Koul sink = p->sink; 866d93f8e55SVinod Koul sink_mconfig = sink->priv; 867d93f8e55SVinod Koul 868b8c722ddSJeeja KP /* 869b8c722ddSJeeja KP * Modules other than PGA leaf can be connected 870b8c722ddSJeeja KP * directly or via switch to a module in another 871b8c722ddSJeeja KP * pipeline. EX: reference path 872b8c722ddSJeeja KP * when the path is enabled, the dst module that needs 873b8c722ddSJeeja KP * to be bound may not be initialized. if the module is 874b8c722ddSJeeja KP * not initialized, add these modules in the deferred 875b8c722ddSJeeja KP * bind list and when the dst module is initialised, 876b8c722ddSJeeja KP * bind this module to the dst_module in deferred list. 877b8c722ddSJeeja KP */ 878b8c722ddSJeeja KP if (((src_mconfig->m_state == SKL_MODULE_INIT_DONE) 879b8c722ddSJeeja KP && (sink_mconfig->m_state == SKL_MODULE_UNINIT))) { 880b8c722ddSJeeja KP 881b8c722ddSJeeja KP ret = skl_tplg_module_add_deferred_bind(skl, 882b8c722ddSJeeja KP src_mconfig, sink_mconfig); 883b8c722ddSJeeja KP 884b8c722ddSJeeja KP if (ret < 0) 885b8c722ddSJeeja KP return ret; 886b8c722ddSJeeja KP 887b8c722ddSJeeja KP } 888b8c722ddSJeeja KP 889b8c722ddSJeeja KP 890cc6a4044SJeeja KP if (src_mconfig->m_state == SKL_MODULE_UNINIT || 891cc6a4044SJeeja KP sink_mconfig->m_state == SKL_MODULE_UNINIT) 892cc6a4044SJeeja KP continue; 893cc6a4044SJeeja KP 894d93f8e55SVinod Koul /* Bind source to sink, mixin is always source */ 895d93f8e55SVinod Koul ret = skl_bind_modules(ctx, src_mconfig, sink_mconfig); 896d93f8e55SVinod Koul if (ret) 897d93f8e55SVinod Koul return ret; 898d93f8e55SVinod Koul 899cc6a4044SJeeja KP /* set module params after bind */ 900cc6a4044SJeeja KP skl_tplg_set_module_bind_params(src_w, src_mconfig, ctx); 901cc6a4044SJeeja KP skl_tplg_set_module_bind_params(sink, sink_mconfig, ctx); 902cc6a4044SJeeja KP 903d93f8e55SVinod Koul /* Start sinks pipe first */ 904d93f8e55SVinod Koul if (sink_mconfig->pipe->state != SKL_PIPE_STARTED) { 905d1730c3dSJeeja KP if (sink_mconfig->pipe->conn_type != 906d1730c3dSJeeja KP SKL_PIPE_CONN_TYPE_FE) 907d1730c3dSJeeja KP ret = skl_run_pipe(ctx, 908d1730c3dSJeeja KP sink_mconfig->pipe); 909d93f8e55SVinod Koul if (ret) 910d93f8e55SVinod Koul return ret; 911d93f8e55SVinod Koul } 912d93f8e55SVinod Koul } 913d93f8e55SVinod Koul } 914d93f8e55SVinod Koul 9158724ff17SJeeja KP if (!sink) 9166bd4cf85SJeeja KP return skl_tplg_bind_sinks(next_sink, skl, src_w, src_mconfig); 9178724ff17SJeeja KP 9188724ff17SJeeja KP return 0; 9198724ff17SJeeja KP } 9208724ff17SJeeja KP 921d93f8e55SVinod Koul /* 922d93f8e55SVinod Koul * A PGA represents a module in a pipeline. So in the Pre-PMU event of PGA 923d93f8e55SVinod Koul * we need to do following: 924d93f8e55SVinod Koul * - Bind to sink pipeline 925d93f8e55SVinod Koul * Since the sink pipes can be running and we don't get mixer event on 926d93f8e55SVinod Koul * connect for already running mixer, we need to find the sink pipes 927d93f8e55SVinod Koul * here and bind to them. This way dynamic connect works. 928d93f8e55SVinod Koul * - Start sink pipeline, if not running 929d93f8e55SVinod Koul * - Then run current pipe 930d93f8e55SVinod Koul */ 931d93f8e55SVinod Koul static int skl_tplg_pga_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w, 932d93f8e55SVinod Koul struct skl *skl) 933d93f8e55SVinod Koul { 9348724ff17SJeeja KP struct skl_module_cfg *src_mconfig; 935d93f8e55SVinod Koul struct skl_sst *ctx = skl->skl_sst; 936d93f8e55SVinod Koul int ret = 0; 937d93f8e55SVinod Koul 9388724ff17SJeeja KP src_mconfig = w->priv; 939d93f8e55SVinod Koul 940d93f8e55SVinod Koul /* 941d93f8e55SVinod Koul * find which sink it is connected to, bind with the sink, 942d93f8e55SVinod Koul * if sink is not started, start sink pipe first, then start 943d93f8e55SVinod Koul * this pipe 944d93f8e55SVinod Koul */ 9456bd4cf85SJeeja KP ret = skl_tplg_bind_sinks(w, skl, w, src_mconfig); 9468724ff17SJeeja KP if (ret) 9478724ff17SJeeja KP return ret; 9488724ff17SJeeja KP 949d93f8e55SVinod Koul /* Start source pipe last after starting all sinks */ 950d1730c3dSJeeja KP if (src_mconfig->pipe->conn_type != SKL_PIPE_CONN_TYPE_FE) 951d1730c3dSJeeja KP return skl_run_pipe(ctx, src_mconfig->pipe); 952d93f8e55SVinod Koul 953d93f8e55SVinod Koul return 0; 954d93f8e55SVinod Koul } 955d93f8e55SVinod Koul 9568724ff17SJeeja KP static struct snd_soc_dapm_widget *skl_get_src_dsp_widget( 9578724ff17SJeeja KP struct snd_soc_dapm_widget *w, struct skl *skl) 9588724ff17SJeeja KP { 9598724ff17SJeeja KP struct snd_soc_dapm_path *p; 9608724ff17SJeeja KP struct snd_soc_dapm_widget *src_w = NULL; 9618724ff17SJeeja KP struct skl_sst *ctx = skl->skl_sst; 9628724ff17SJeeja KP 963d93f8e55SVinod Koul snd_soc_dapm_widget_for_each_source_path(w, p) { 9648724ff17SJeeja KP src_w = p->source; 965d93f8e55SVinod Koul if (!p->connect) 966d93f8e55SVinod Koul continue; 967d93f8e55SVinod Koul 9688724ff17SJeeja KP dev_dbg(ctx->dev, "sink widget=%s\n", w->name); 9698724ff17SJeeja KP dev_dbg(ctx->dev, "src widget=%s\n", p->source->name); 970d93f8e55SVinod Koul 971d93f8e55SVinod Koul /* 9728724ff17SJeeja KP * here we will check widgets in sink pipelines, so that can 9738724ff17SJeeja KP * be any widgets type and we are only interested if they are 9748724ff17SJeeja KP * ones used for SKL so check that first 975d93f8e55SVinod Koul */ 9768724ff17SJeeja KP if ((p->source->priv != NULL) && 9778724ff17SJeeja KP is_skl_dsp_widget_type(p->source)) { 9788724ff17SJeeja KP return p->source; 979d93f8e55SVinod Koul } 980d93f8e55SVinod Koul } 981d93f8e55SVinod Koul 9828724ff17SJeeja KP if (src_w != NULL) 9838724ff17SJeeja KP return skl_get_src_dsp_widget(src_w, skl); 984d93f8e55SVinod Koul 9858724ff17SJeeja KP return NULL; 986d93f8e55SVinod Koul } 987d93f8e55SVinod Koul 988d93f8e55SVinod Koul /* 989d93f8e55SVinod Koul * in the Post-PMU event of mixer we need to do following: 990d93f8e55SVinod Koul * - Check if this pipe is running 991d93f8e55SVinod Koul * - if not, then 992d93f8e55SVinod Koul * - bind this pipeline to its source pipeline 993d93f8e55SVinod Koul * if source pipe is already running, this means it is a dynamic 994d93f8e55SVinod Koul * connection and we need to bind only to that pipe 995d93f8e55SVinod Koul * - start this pipeline 996d93f8e55SVinod Koul */ 997d93f8e55SVinod Koul static int skl_tplg_mixer_dapm_post_pmu_event(struct snd_soc_dapm_widget *w, 998d93f8e55SVinod Koul struct skl *skl) 999d93f8e55SVinod Koul { 1000d93f8e55SVinod Koul int ret = 0; 1001d93f8e55SVinod Koul struct snd_soc_dapm_widget *source, *sink; 1002d93f8e55SVinod Koul struct skl_module_cfg *src_mconfig, *sink_mconfig; 1003d93f8e55SVinod Koul struct skl_sst *ctx = skl->skl_sst; 1004d93f8e55SVinod Koul int src_pipe_started = 0; 1005d93f8e55SVinod Koul 1006d93f8e55SVinod Koul sink = w; 1007d93f8e55SVinod Koul sink_mconfig = sink->priv; 1008d93f8e55SVinod Koul 1009d93f8e55SVinod Koul /* 1010d93f8e55SVinod Koul * If source pipe is already started, that means source is driving 1011d93f8e55SVinod Koul * one more sink before this sink got connected, Since source is 1012d93f8e55SVinod Koul * started, bind this sink to source and start this pipe. 1013d93f8e55SVinod Koul */ 10148724ff17SJeeja KP source = skl_get_src_dsp_widget(w, skl); 10158724ff17SJeeja KP if (source != NULL) { 1016d93f8e55SVinod Koul src_mconfig = source->priv; 1017d93f8e55SVinod Koul sink_mconfig = sink->priv; 1018d93f8e55SVinod Koul src_pipe_started = 1; 1019d93f8e55SVinod Koul 1020d93f8e55SVinod Koul /* 10218724ff17SJeeja KP * check pipe state, then no need to bind or start the 10228724ff17SJeeja KP * pipe 1023d93f8e55SVinod Koul */ 1024d93f8e55SVinod Koul if (src_mconfig->pipe->state != SKL_PIPE_STARTED) 1025d93f8e55SVinod Koul src_pipe_started = 0; 1026d93f8e55SVinod Koul } 1027d93f8e55SVinod Koul 1028d93f8e55SVinod Koul if (src_pipe_started) { 1029d93f8e55SVinod Koul ret = skl_bind_modules(ctx, src_mconfig, sink_mconfig); 1030d93f8e55SVinod Koul if (ret) 1031d93f8e55SVinod Koul return ret; 1032d93f8e55SVinod Koul 1033cc6a4044SJeeja KP /* set module params after bind */ 1034cc6a4044SJeeja KP skl_tplg_set_module_bind_params(source, src_mconfig, ctx); 1035cc6a4044SJeeja KP skl_tplg_set_module_bind_params(sink, sink_mconfig, ctx); 1036cc6a4044SJeeja KP 1037d1730c3dSJeeja KP if (sink_mconfig->pipe->conn_type != SKL_PIPE_CONN_TYPE_FE) 1038d93f8e55SVinod Koul ret = skl_run_pipe(ctx, sink_mconfig->pipe); 1039d93f8e55SVinod Koul } 1040d93f8e55SVinod Koul 1041d93f8e55SVinod Koul return ret; 1042d93f8e55SVinod Koul } 1043d93f8e55SVinod Koul 1044d93f8e55SVinod Koul /* 1045d93f8e55SVinod Koul * in the Pre-PMD event of mixer we need to do following: 1046d93f8e55SVinod Koul * - Stop the pipe 1047d93f8e55SVinod Koul * - find the source connections and remove that from dapm_path_list 1048d93f8e55SVinod Koul * - unbind with source pipelines if still connected 1049d93f8e55SVinod Koul */ 1050d93f8e55SVinod Koul static int skl_tplg_mixer_dapm_pre_pmd_event(struct snd_soc_dapm_widget *w, 1051d93f8e55SVinod Koul struct skl *skl) 1052d93f8e55SVinod Koul { 1053d93f8e55SVinod Koul struct skl_module_cfg *src_mconfig, *sink_mconfig; 1054ce1b5551SJeeja KP int ret = 0, i; 1055d93f8e55SVinod Koul struct skl_sst *ctx = skl->skl_sst; 1056d93f8e55SVinod Koul 1057ce1b5551SJeeja KP sink_mconfig = w->priv; 1058d93f8e55SVinod Koul 1059d93f8e55SVinod Koul /* Stop the pipe */ 1060d93f8e55SVinod Koul ret = skl_stop_pipe(ctx, sink_mconfig->pipe); 1061d93f8e55SVinod Koul if (ret) 1062d93f8e55SVinod Koul return ret; 1063d93f8e55SVinod Koul 1064ce1b5551SJeeja KP for (i = 0; i < sink_mconfig->max_in_queue; i++) { 1065ce1b5551SJeeja KP if (sink_mconfig->m_in_pin[i].pin_state == SKL_PIN_BIND_DONE) { 1066ce1b5551SJeeja KP src_mconfig = sink_mconfig->m_in_pin[i].tgt_mcfg; 1067ce1b5551SJeeja KP if (!src_mconfig) 1068ce1b5551SJeeja KP continue; 1069d93f8e55SVinod Koul 1070ce1b5551SJeeja KP ret = skl_unbind_modules(ctx, 1071ce1b5551SJeeja KP src_mconfig, sink_mconfig); 1072ce1b5551SJeeja KP } 1073d93f8e55SVinod Koul } 1074d93f8e55SVinod Koul 1075d93f8e55SVinod Koul return ret; 1076d93f8e55SVinod Koul } 1077d93f8e55SVinod Koul 1078d93f8e55SVinod Koul /* 1079d93f8e55SVinod Koul * in the Post-PMD event of mixer we need to do following: 1080d93f8e55SVinod Koul * - Free the mcps used 1081d93f8e55SVinod Koul * - Free the mem used 1082d93f8e55SVinod Koul * - Unbind the modules within the pipeline 1083d93f8e55SVinod Koul * - Delete the pipeline (modules are not required to be explicitly 1084d93f8e55SVinod Koul * deleted, pipeline delete is enough here 1085d93f8e55SVinod Koul */ 1086d93f8e55SVinod Koul static int skl_tplg_mixer_dapm_post_pmd_event(struct snd_soc_dapm_widget *w, 1087d93f8e55SVinod Koul struct skl *skl) 1088d93f8e55SVinod Koul { 1089d93f8e55SVinod Koul struct skl_module_cfg *mconfig = w->priv; 1090d93f8e55SVinod Koul struct skl_pipe_module *w_module; 1091d93f8e55SVinod Koul struct skl_module_cfg *src_module = NULL, *dst_module; 1092d93f8e55SVinod Koul struct skl_sst *ctx = skl->skl_sst; 1093d93f8e55SVinod Koul struct skl_pipe *s_pipe = mconfig->pipe; 1094*550b349aSDan Carpenter struct skl_module_deferred_bind *modules, *tmp; 1095d93f8e55SVinod Koul 1096260eb73aSDharageswari R if (s_pipe->state == SKL_PIPE_INVALID) 1097260eb73aSDharageswari R return -EINVAL; 1098260eb73aSDharageswari R 1099d93f8e55SVinod Koul skl_tplg_free_pipe_mcps(skl, mconfig); 110065976878SVinod Koul skl_tplg_free_pipe_mem(skl, mconfig); 1101d93f8e55SVinod Koul 1102d93f8e55SVinod Koul list_for_each_entry(w_module, &s_pipe->w_list, node) { 1103b8c722ddSJeeja KP if (list_empty(&skl->bind_list)) 1104b8c722ddSJeeja KP break; 1105b8c722ddSJeeja KP 1106b8c722ddSJeeja KP src_module = w_module->w->priv; 1107b8c722ddSJeeja KP 1108*550b349aSDan Carpenter list_for_each_entry_safe(modules, tmp, &skl->bind_list, node) { 1109b8c722ddSJeeja KP /* 1110b8c722ddSJeeja KP * When the destination module is deleted, Unbind the 1111b8c722ddSJeeja KP * modules from deferred bind list. 1112b8c722ddSJeeja KP */ 1113b8c722ddSJeeja KP if (modules->dst == src_module) { 1114b8c722ddSJeeja KP skl_unbind_modules(ctx, modules->src, 1115b8c722ddSJeeja KP modules->dst); 1116b8c722ddSJeeja KP } 1117b8c722ddSJeeja KP 1118b8c722ddSJeeja KP /* 1119b8c722ddSJeeja KP * When the source module is deleted, remove this entry 1120b8c722ddSJeeja KP * from the deferred bind list. 1121b8c722ddSJeeja KP */ 1122b8c722ddSJeeja KP if (modules->src == src_module) { 1123b8c722ddSJeeja KP list_del(&modules->node); 1124b8c722ddSJeeja KP modules->src = NULL; 1125b8c722ddSJeeja KP modules->dst = NULL; 1126b8c722ddSJeeja KP kfree(modules); 1127b8c722ddSJeeja KP } 1128b8c722ddSJeeja KP } 1129b8c722ddSJeeja KP } 1130b8c722ddSJeeja KP 1131b8c722ddSJeeja KP list_for_each_entry(w_module, &s_pipe->w_list, node) { 1132d93f8e55SVinod Koul dst_module = w_module->w->priv; 1133d93f8e55SVinod Koul 1134260eb73aSDharageswari R if (mconfig->m_state >= SKL_MODULE_INIT_DONE) 11357ae3cb15SVinod Koul skl_tplg_free_pipe_mcps(skl, dst_module); 1136d93f8e55SVinod Koul if (src_module == NULL) { 1137d93f8e55SVinod Koul src_module = dst_module; 1138d93f8e55SVinod Koul continue; 1139d93f8e55SVinod Koul } 1140d93f8e55SVinod Koul 11417ca42f5aSGuneshwor Singh skl_unbind_modules(ctx, src_module, dst_module); 1142d93f8e55SVinod Koul src_module = dst_module; 1143d93f8e55SVinod Koul } 1144d93f8e55SVinod Koul 1145547cafa3SVinod Koul skl_delete_pipe(ctx, mconfig->pipe); 1146d93f8e55SVinod Koul 1147473a4d51SJeeja KP list_for_each_entry(w_module, &s_pipe->w_list, node) { 1148473a4d51SJeeja KP src_module = w_module->w->priv; 1149473a4d51SJeeja KP src_module->m_state = SKL_MODULE_UNINIT; 1150473a4d51SJeeja KP } 1151473a4d51SJeeja KP 11526c5768b3SDharageswari R return skl_tplg_unload_pipe_modules(ctx, s_pipe); 1153d93f8e55SVinod Koul } 1154d93f8e55SVinod Koul 1155d93f8e55SVinod Koul /* 1156d93f8e55SVinod Koul * in the Post-PMD event of PGA we need to do following: 1157d93f8e55SVinod Koul * - Free the mcps used 1158d93f8e55SVinod Koul * - Stop the pipeline 1159d93f8e55SVinod Koul * - In source pipe is connected, unbind with source pipelines 1160d93f8e55SVinod Koul */ 1161d93f8e55SVinod Koul static int skl_tplg_pga_dapm_post_pmd_event(struct snd_soc_dapm_widget *w, 1162d93f8e55SVinod Koul struct skl *skl) 1163d93f8e55SVinod Koul { 1164d93f8e55SVinod Koul struct skl_module_cfg *src_mconfig, *sink_mconfig; 1165ce1b5551SJeeja KP int ret = 0, i; 1166d93f8e55SVinod Koul struct skl_sst *ctx = skl->skl_sst; 1167d93f8e55SVinod Koul 1168ce1b5551SJeeja KP src_mconfig = w->priv; 1169d93f8e55SVinod Koul 1170d93f8e55SVinod Koul /* Stop the pipe since this is a mixin module */ 1171d93f8e55SVinod Koul ret = skl_stop_pipe(ctx, src_mconfig->pipe); 1172d93f8e55SVinod Koul if (ret) 1173d93f8e55SVinod Koul return ret; 1174d93f8e55SVinod Koul 1175ce1b5551SJeeja KP for (i = 0; i < src_mconfig->max_out_queue; i++) { 1176ce1b5551SJeeja KP if (src_mconfig->m_out_pin[i].pin_state == SKL_PIN_BIND_DONE) { 1177ce1b5551SJeeja KP sink_mconfig = src_mconfig->m_out_pin[i].tgt_mcfg; 1178ce1b5551SJeeja KP if (!sink_mconfig) 1179ce1b5551SJeeja KP continue; 1180d93f8e55SVinod Koul /* 1181ce1b5551SJeeja KP * This is a connecter and if path is found that means 1182d93f8e55SVinod Koul * unbind between source and sink has not happened yet 1183d93f8e55SVinod Koul */ 1184ce1b5551SJeeja KP ret = skl_unbind_modules(ctx, src_mconfig, 1185ce1b5551SJeeja KP sink_mconfig); 1186ce1b5551SJeeja KP } 1187d93f8e55SVinod Koul } 1188d93f8e55SVinod Koul 1189d93f8e55SVinod Koul return ret; 1190d93f8e55SVinod Koul } 1191d93f8e55SVinod Koul 1192d93f8e55SVinod Koul /* 1193d93f8e55SVinod Koul * In modelling, we assume there will be ONLY one mixer in a pipeline. If a 1194d93f8e55SVinod Koul * second one is required that is created as another pipe entity. 1195d93f8e55SVinod Koul * The mixer is responsible for pipe management and represent a pipeline 1196d93f8e55SVinod Koul * instance 1197d93f8e55SVinod Koul */ 1198d93f8e55SVinod Koul static int skl_tplg_mixer_event(struct snd_soc_dapm_widget *w, 1199d93f8e55SVinod Koul struct snd_kcontrol *k, int event) 1200d93f8e55SVinod Koul { 1201d93f8e55SVinod Koul struct snd_soc_dapm_context *dapm = w->dapm; 1202d93f8e55SVinod Koul struct skl *skl = get_skl_ctx(dapm->dev); 1203d93f8e55SVinod Koul 1204d93f8e55SVinod Koul switch (event) { 1205d93f8e55SVinod Koul case SND_SOC_DAPM_PRE_PMU: 1206d93f8e55SVinod Koul return skl_tplg_mixer_dapm_pre_pmu_event(w, skl); 1207d93f8e55SVinod Koul 1208d93f8e55SVinod Koul case SND_SOC_DAPM_POST_PMU: 1209d93f8e55SVinod Koul return skl_tplg_mixer_dapm_post_pmu_event(w, skl); 1210d93f8e55SVinod Koul 1211d93f8e55SVinod Koul case SND_SOC_DAPM_PRE_PMD: 1212d93f8e55SVinod Koul return skl_tplg_mixer_dapm_pre_pmd_event(w, skl); 1213d93f8e55SVinod Koul 1214d93f8e55SVinod Koul case SND_SOC_DAPM_POST_PMD: 1215d93f8e55SVinod Koul return skl_tplg_mixer_dapm_post_pmd_event(w, skl); 1216d93f8e55SVinod Koul } 1217d93f8e55SVinod Koul 1218d93f8e55SVinod Koul return 0; 1219d93f8e55SVinod Koul } 1220d93f8e55SVinod Koul 1221d93f8e55SVinod Koul /* 1222d93f8e55SVinod Koul * In modelling, we assumed rest of the modules in pipeline are PGA. But we 1223d93f8e55SVinod Koul * are interested in last PGA (leaf PGA) in a pipeline to disconnect with 1224d93f8e55SVinod Koul * the sink when it is running (two FE to one BE or one FE to two BE) 1225d93f8e55SVinod Koul * scenarios 1226d93f8e55SVinod Koul */ 1227d93f8e55SVinod Koul static int skl_tplg_pga_event(struct snd_soc_dapm_widget *w, 1228d93f8e55SVinod Koul struct snd_kcontrol *k, int event) 1229d93f8e55SVinod Koul 1230d93f8e55SVinod Koul { 1231d93f8e55SVinod Koul struct snd_soc_dapm_context *dapm = w->dapm; 1232d93f8e55SVinod Koul struct skl *skl = get_skl_ctx(dapm->dev); 1233d93f8e55SVinod Koul 1234d93f8e55SVinod Koul switch (event) { 1235d93f8e55SVinod Koul case SND_SOC_DAPM_PRE_PMU: 1236d93f8e55SVinod Koul return skl_tplg_pga_dapm_pre_pmu_event(w, skl); 1237d93f8e55SVinod Koul 1238d93f8e55SVinod Koul case SND_SOC_DAPM_POST_PMD: 1239d93f8e55SVinod Koul return skl_tplg_pga_dapm_post_pmd_event(w, skl); 1240d93f8e55SVinod Koul } 1241d93f8e55SVinod Koul 1242d93f8e55SVinod Koul return 0; 1243d93f8e55SVinod Koul } 1244cfb0a873SVinod Koul 1245140adfbaSJeeja KP static int skl_tplg_tlv_control_get(struct snd_kcontrol *kcontrol, 1246140adfbaSJeeja KP unsigned int __user *data, unsigned int size) 1247140adfbaSJeeja KP { 1248140adfbaSJeeja KP struct soc_bytes_ext *sb = 1249140adfbaSJeeja KP (struct soc_bytes_ext *)kcontrol->private_value; 1250140adfbaSJeeja KP struct skl_algo_data *bc = (struct skl_algo_data *)sb->dobj.private; 12517d9f2911SOmair M Abdullah struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol); 12527d9f2911SOmair M Abdullah struct skl_module_cfg *mconfig = w->priv; 12537d9f2911SOmair M Abdullah struct skl *skl = get_skl_ctx(w->dapm->dev); 12547d9f2911SOmair M Abdullah 12557d9f2911SOmair M Abdullah if (w->power) 12567d9f2911SOmair M Abdullah skl_get_module_params(skl->skl_sst, (u32 *)bc->params, 12570d682104SDharageswari R bc->size, bc->param_id, mconfig); 1258140adfbaSJeeja KP 125941556f68SVinod Koul /* decrement size for TLV header */ 126041556f68SVinod Koul size -= 2 * sizeof(u32); 126141556f68SVinod Koul 126241556f68SVinod Koul /* check size as we don't want to send kernel data */ 126341556f68SVinod Koul if (size > bc->max) 126441556f68SVinod Koul size = bc->max; 126541556f68SVinod Koul 1266140adfbaSJeeja KP if (bc->params) { 1267140adfbaSJeeja KP if (copy_to_user(data, &bc->param_id, sizeof(u32))) 1268140adfbaSJeeja KP return -EFAULT; 1269e8bc3c99SDan Carpenter if (copy_to_user(data + 1, &size, sizeof(u32))) 1270140adfbaSJeeja KP return -EFAULT; 1271e8bc3c99SDan Carpenter if (copy_to_user(data + 2, bc->params, size)) 1272140adfbaSJeeja KP return -EFAULT; 1273140adfbaSJeeja KP } 1274140adfbaSJeeja KP 1275140adfbaSJeeja KP return 0; 1276140adfbaSJeeja KP } 1277140adfbaSJeeja KP 1278140adfbaSJeeja KP #define SKL_PARAM_VENDOR_ID 0xff 1279140adfbaSJeeja KP 1280140adfbaSJeeja KP static int skl_tplg_tlv_control_set(struct snd_kcontrol *kcontrol, 1281140adfbaSJeeja KP const unsigned int __user *data, unsigned int size) 1282140adfbaSJeeja KP { 1283140adfbaSJeeja KP struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol); 1284140adfbaSJeeja KP struct skl_module_cfg *mconfig = w->priv; 1285140adfbaSJeeja KP struct soc_bytes_ext *sb = 1286140adfbaSJeeja KP (struct soc_bytes_ext *)kcontrol->private_value; 1287140adfbaSJeeja KP struct skl_algo_data *ac = (struct skl_algo_data *)sb->dobj.private; 1288140adfbaSJeeja KP struct skl *skl = get_skl_ctx(w->dapm->dev); 1289140adfbaSJeeja KP 1290140adfbaSJeeja KP if (ac->params) { 12910d682104SDharageswari R if (size > ac->max) 12920d682104SDharageswari R return -EINVAL; 12930d682104SDharageswari R 12940d682104SDharageswari R ac->size = size; 1295140adfbaSJeeja KP /* 1296140adfbaSJeeja KP * if the param_is is of type Vendor, firmware expects actual 1297140adfbaSJeeja KP * parameter id and size from the control. 1298140adfbaSJeeja KP */ 1299140adfbaSJeeja KP if (ac->param_id == SKL_PARAM_VENDOR_ID) { 1300140adfbaSJeeja KP if (copy_from_user(ac->params, data, size)) 1301140adfbaSJeeja KP return -EFAULT; 1302140adfbaSJeeja KP } else { 1303140adfbaSJeeja KP if (copy_from_user(ac->params, 130465b4bcb8SAlan data + 2, size)) 1305140adfbaSJeeja KP return -EFAULT; 1306140adfbaSJeeja KP } 1307140adfbaSJeeja KP 1308140adfbaSJeeja KP if (w->power) 1309140adfbaSJeeja KP return skl_set_module_params(skl->skl_sst, 13100d682104SDharageswari R (u32 *)ac->params, ac->size, 1311140adfbaSJeeja KP ac->param_id, mconfig); 1312140adfbaSJeeja KP } 1313140adfbaSJeeja KP 1314140adfbaSJeeja KP return 0; 1315140adfbaSJeeja KP } 1316140adfbaSJeeja KP 1317cfb0a873SVinod Koul /* 13188871dcb9SJeeja KP * Fill the dma id for host and link. In case of passthrough 13198871dcb9SJeeja KP * pipeline, this will both host and link in the same 13208871dcb9SJeeja KP * pipeline, so need to copy the link and host based on dev_type 13218871dcb9SJeeja KP */ 13228871dcb9SJeeja KP static void skl_tplg_fill_dma_id(struct skl_module_cfg *mcfg, 13238871dcb9SJeeja KP struct skl_pipe_params *params) 13248871dcb9SJeeja KP { 13258871dcb9SJeeja KP struct skl_pipe *pipe = mcfg->pipe; 13268871dcb9SJeeja KP 13278871dcb9SJeeja KP if (pipe->passthru) { 13288871dcb9SJeeja KP switch (mcfg->dev_type) { 13298871dcb9SJeeja KP case SKL_DEVICE_HDALINK: 13308871dcb9SJeeja KP pipe->p_params->link_dma_id = params->link_dma_id; 133112c3be0eSJeeja KP pipe->p_params->link_index = params->link_index; 13327f975a38SJeeja KP pipe->p_params->link_bps = params->link_bps; 13338871dcb9SJeeja KP break; 13348871dcb9SJeeja KP 13358871dcb9SJeeja KP case SKL_DEVICE_HDAHOST: 13368871dcb9SJeeja KP pipe->p_params->host_dma_id = params->host_dma_id; 13377f975a38SJeeja KP pipe->p_params->host_bps = params->host_bps; 13388871dcb9SJeeja KP break; 13398871dcb9SJeeja KP 13408871dcb9SJeeja KP default: 13418871dcb9SJeeja KP break; 13428871dcb9SJeeja KP } 13438871dcb9SJeeja KP pipe->p_params->s_fmt = params->s_fmt; 13448871dcb9SJeeja KP pipe->p_params->ch = params->ch; 13458871dcb9SJeeja KP pipe->p_params->s_freq = params->s_freq; 13468871dcb9SJeeja KP pipe->p_params->stream = params->stream; 134712c3be0eSJeeja KP pipe->p_params->format = params->format; 13488871dcb9SJeeja KP 13498871dcb9SJeeja KP } else { 13508871dcb9SJeeja KP memcpy(pipe->p_params, params, sizeof(*params)); 13518871dcb9SJeeja KP } 13528871dcb9SJeeja KP } 13538871dcb9SJeeja KP 13548871dcb9SJeeja KP /* 1355cfb0a873SVinod Koul * The FE params are passed by hw_params of the DAI. 1356cfb0a873SVinod Koul * On hw_params, the params are stored in Gateway module of the FE and we 1357cfb0a873SVinod Koul * need to calculate the format in DSP module configuration, that 1358cfb0a873SVinod Koul * conversion is done here 1359cfb0a873SVinod Koul */ 1360cfb0a873SVinod Koul int skl_tplg_update_pipe_params(struct device *dev, 1361cfb0a873SVinod Koul struct skl_module_cfg *mconfig, 1362cfb0a873SVinod Koul struct skl_pipe_params *params) 1363cfb0a873SVinod Koul { 1364cfb0a873SVinod Koul struct skl_module_fmt *format = NULL; 1365cfb0a873SVinod Koul 13668871dcb9SJeeja KP skl_tplg_fill_dma_id(mconfig, params); 1367cfb0a873SVinod Koul 1368cfb0a873SVinod Koul if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) 13694cd9899fSHardik T Shah format = &mconfig->in_fmt[0]; 1370cfb0a873SVinod Koul else 13714cd9899fSHardik T Shah format = &mconfig->out_fmt[0]; 1372cfb0a873SVinod Koul 1373cfb0a873SVinod Koul /* set the hw_params */ 1374cfb0a873SVinod Koul format->s_freq = params->s_freq; 1375cfb0a873SVinod Koul format->channels = params->ch; 1376cfb0a873SVinod Koul format->valid_bit_depth = skl_get_bit_depth(params->s_fmt); 1377cfb0a873SVinod Koul 1378cfb0a873SVinod Koul /* 1379cfb0a873SVinod Koul * 16 bit is 16 bit container whereas 24 bit is in 32 bit 1380cfb0a873SVinod Koul * container so update bit depth accordingly 1381cfb0a873SVinod Koul */ 1382cfb0a873SVinod Koul switch (format->valid_bit_depth) { 1383cfb0a873SVinod Koul case SKL_DEPTH_16BIT: 1384cfb0a873SVinod Koul format->bit_depth = format->valid_bit_depth; 1385cfb0a873SVinod Koul break; 1386cfb0a873SVinod Koul 1387cfb0a873SVinod Koul case SKL_DEPTH_24BIT: 13886654f39eSJeeja KP case SKL_DEPTH_32BIT: 1389cfb0a873SVinod Koul format->bit_depth = SKL_DEPTH_32BIT; 1390cfb0a873SVinod Koul break; 1391cfb0a873SVinod Koul 1392cfb0a873SVinod Koul default: 1393cfb0a873SVinod Koul dev_err(dev, "Invalid bit depth %x for pipe\n", 1394cfb0a873SVinod Koul format->valid_bit_depth); 1395cfb0a873SVinod Koul return -EINVAL; 1396cfb0a873SVinod Koul } 1397cfb0a873SVinod Koul 1398cfb0a873SVinod Koul if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) { 1399cfb0a873SVinod Koul mconfig->ibs = (format->s_freq / 1000) * 1400cfb0a873SVinod Koul (format->channels) * 1401cfb0a873SVinod Koul (format->bit_depth >> 3); 1402cfb0a873SVinod Koul } else { 1403cfb0a873SVinod Koul mconfig->obs = (format->s_freq / 1000) * 1404cfb0a873SVinod Koul (format->channels) * 1405cfb0a873SVinod Koul (format->bit_depth >> 3); 1406cfb0a873SVinod Koul } 1407cfb0a873SVinod Koul 1408cfb0a873SVinod Koul return 0; 1409cfb0a873SVinod Koul } 1410cfb0a873SVinod Koul 1411cfb0a873SVinod Koul /* 1412cfb0a873SVinod Koul * Query the module config for the FE DAI 1413cfb0a873SVinod Koul * This is used to find the hw_params set for that DAI and apply to FE 1414cfb0a873SVinod Koul * pipeline 1415cfb0a873SVinod Koul */ 1416cfb0a873SVinod Koul struct skl_module_cfg * 1417cfb0a873SVinod Koul skl_tplg_fe_get_cpr_module(struct snd_soc_dai *dai, int stream) 1418cfb0a873SVinod Koul { 1419cfb0a873SVinod Koul struct snd_soc_dapm_widget *w; 1420cfb0a873SVinod Koul struct snd_soc_dapm_path *p = NULL; 1421cfb0a873SVinod Koul 1422cfb0a873SVinod Koul if (stream == SNDRV_PCM_STREAM_PLAYBACK) { 1423cfb0a873SVinod Koul w = dai->playback_widget; 1424f0900eb2SSubhransu S. Prusty snd_soc_dapm_widget_for_each_sink_path(w, p) { 1425cfb0a873SVinod Koul if (p->connect && p->sink->power && 1426a28f51dbSJeeja KP !is_skl_dsp_widget_type(p->sink)) 1427cfb0a873SVinod Koul continue; 1428cfb0a873SVinod Koul 1429cfb0a873SVinod Koul if (p->sink->priv) { 1430cfb0a873SVinod Koul dev_dbg(dai->dev, "set params for %s\n", 1431cfb0a873SVinod Koul p->sink->name); 1432cfb0a873SVinod Koul return p->sink->priv; 1433cfb0a873SVinod Koul } 1434cfb0a873SVinod Koul } 1435cfb0a873SVinod Koul } else { 1436cfb0a873SVinod Koul w = dai->capture_widget; 1437f0900eb2SSubhransu S. Prusty snd_soc_dapm_widget_for_each_source_path(w, p) { 1438cfb0a873SVinod Koul if (p->connect && p->source->power && 1439a28f51dbSJeeja KP !is_skl_dsp_widget_type(p->source)) 1440cfb0a873SVinod Koul continue; 1441cfb0a873SVinod Koul 1442cfb0a873SVinod Koul if (p->source->priv) { 1443cfb0a873SVinod Koul dev_dbg(dai->dev, "set params for %s\n", 1444cfb0a873SVinod Koul p->source->name); 1445cfb0a873SVinod Koul return p->source->priv; 1446cfb0a873SVinod Koul } 1447cfb0a873SVinod Koul } 1448cfb0a873SVinod Koul } 1449cfb0a873SVinod Koul 1450cfb0a873SVinod Koul return NULL; 1451cfb0a873SVinod Koul } 1452cfb0a873SVinod Koul 1453718a42b5SDharageswari.R static struct skl_module_cfg *skl_get_mconfig_pb_cpr( 1454718a42b5SDharageswari.R struct snd_soc_dai *dai, struct snd_soc_dapm_widget *w) 1455718a42b5SDharageswari.R { 1456718a42b5SDharageswari.R struct snd_soc_dapm_path *p; 1457718a42b5SDharageswari.R struct skl_module_cfg *mconfig = NULL; 1458718a42b5SDharageswari.R 1459718a42b5SDharageswari.R snd_soc_dapm_widget_for_each_source_path(w, p) { 1460718a42b5SDharageswari.R if (w->endpoints[SND_SOC_DAPM_DIR_OUT] > 0) { 1461718a42b5SDharageswari.R if (p->connect && 1462718a42b5SDharageswari.R (p->sink->id == snd_soc_dapm_aif_out) && 1463718a42b5SDharageswari.R p->source->priv) { 1464718a42b5SDharageswari.R mconfig = p->source->priv; 1465718a42b5SDharageswari.R return mconfig; 1466718a42b5SDharageswari.R } 1467718a42b5SDharageswari.R mconfig = skl_get_mconfig_pb_cpr(dai, p->source); 1468718a42b5SDharageswari.R if (mconfig) 1469718a42b5SDharageswari.R return mconfig; 1470718a42b5SDharageswari.R } 1471718a42b5SDharageswari.R } 1472718a42b5SDharageswari.R return mconfig; 1473718a42b5SDharageswari.R } 1474718a42b5SDharageswari.R 1475718a42b5SDharageswari.R static struct skl_module_cfg *skl_get_mconfig_cap_cpr( 1476718a42b5SDharageswari.R struct snd_soc_dai *dai, struct snd_soc_dapm_widget *w) 1477718a42b5SDharageswari.R { 1478718a42b5SDharageswari.R struct snd_soc_dapm_path *p; 1479718a42b5SDharageswari.R struct skl_module_cfg *mconfig = NULL; 1480718a42b5SDharageswari.R 1481718a42b5SDharageswari.R snd_soc_dapm_widget_for_each_sink_path(w, p) { 1482718a42b5SDharageswari.R if (w->endpoints[SND_SOC_DAPM_DIR_IN] > 0) { 1483718a42b5SDharageswari.R if (p->connect && 1484718a42b5SDharageswari.R (p->source->id == snd_soc_dapm_aif_in) && 1485718a42b5SDharageswari.R p->sink->priv) { 1486718a42b5SDharageswari.R mconfig = p->sink->priv; 1487718a42b5SDharageswari.R return mconfig; 1488718a42b5SDharageswari.R } 1489718a42b5SDharageswari.R mconfig = skl_get_mconfig_cap_cpr(dai, p->sink); 1490718a42b5SDharageswari.R if (mconfig) 1491718a42b5SDharageswari.R return mconfig; 1492718a42b5SDharageswari.R } 1493718a42b5SDharageswari.R } 1494718a42b5SDharageswari.R return mconfig; 1495718a42b5SDharageswari.R } 1496718a42b5SDharageswari.R 1497718a42b5SDharageswari.R struct skl_module_cfg * 1498718a42b5SDharageswari.R skl_tplg_be_get_cpr_module(struct snd_soc_dai *dai, int stream) 1499718a42b5SDharageswari.R { 1500718a42b5SDharageswari.R struct snd_soc_dapm_widget *w; 1501718a42b5SDharageswari.R struct skl_module_cfg *mconfig; 1502718a42b5SDharageswari.R 1503718a42b5SDharageswari.R if (stream == SNDRV_PCM_STREAM_PLAYBACK) { 1504718a42b5SDharageswari.R w = dai->playback_widget; 1505718a42b5SDharageswari.R mconfig = skl_get_mconfig_pb_cpr(dai, w); 1506718a42b5SDharageswari.R } else { 1507718a42b5SDharageswari.R w = dai->capture_widget; 1508718a42b5SDharageswari.R mconfig = skl_get_mconfig_cap_cpr(dai, w); 1509718a42b5SDharageswari.R } 1510718a42b5SDharageswari.R return mconfig; 1511718a42b5SDharageswari.R } 1512718a42b5SDharageswari.R 1513cfb0a873SVinod Koul static u8 skl_tplg_be_link_type(int dev_type) 1514cfb0a873SVinod Koul { 1515cfb0a873SVinod Koul int ret; 1516cfb0a873SVinod Koul 1517cfb0a873SVinod Koul switch (dev_type) { 1518cfb0a873SVinod Koul case SKL_DEVICE_BT: 1519cfb0a873SVinod Koul ret = NHLT_LINK_SSP; 1520cfb0a873SVinod Koul break; 1521cfb0a873SVinod Koul 1522cfb0a873SVinod Koul case SKL_DEVICE_DMIC: 1523cfb0a873SVinod Koul ret = NHLT_LINK_DMIC; 1524cfb0a873SVinod Koul break; 1525cfb0a873SVinod Koul 1526cfb0a873SVinod Koul case SKL_DEVICE_I2S: 1527cfb0a873SVinod Koul ret = NHLT_LINK_SSP; 1528cfb0a873SVinod Koul break; 1529cfb0a873SVinod Koul 1530cfb0a873SVinod Koul case SKL_DEVICE_HDALINK: 1531cfb0a873SVinod Koul ret = NHLT_LINK_HDA; 1532cfb0a873SVinod Koul break; 1533cfb0a873SVinod Koul 1534cfb0a873SVinod Koul default: 1535cfb0a873SVinod Koul ret = NHLT_LINK_INVALID; 1536cfb0a873SVinod Koul break; 1537cfb0a873SVinod Koul } 1538cfb0a873SVinod Koul 1539cfb0a873SVinod Koul return ret; 1540cfb0a873SVinod Koul } 1541cfb0a873SVinod Koul 1542cfb0a873SVinod Koul /* 1543cfb0a873SVinod Koul * Fill the BE gateway parameters 1544cfb0a873SVinod Koul * The BE gateway expects a blob of parameters which are kept in the ACPI 1545cfb0a873SVinod Koul * NHLT blob, so query the blob for interface type (i2s/pdm) and instance. 1546cfb0a873SVinod Koul * The port can have multiple settings so pick based on the PCM 1547cfb0a873SVinod Koul * parameters 1548cfb0a873SVinod Koul */ 1549cfb0a873SVinod Koul static int skl_tplg_be_fill_pipe_params(struct snd_soc_dai *dai, 1550cfb0a873SVinod Koul struct skl_module_cfg *mconfig, 1551cfb0a873SVinod Koul struct skl_pipe_params *params) 1552cfb0a873SVinod Koul { 1553cfb0a873SVinod Koul struct nhlt_specific_cfg *cfg; 1554cfb0a873SVinod Koul struct skl *skl = get_skl_ctx(dai->dev); 1555cfb0a873SVinod Koul int link_type = skl_tplg_be_link_type(mconfig->dev_type); 1556db2f586bSSenthilnathan Veppur u8 dev_type = skl_tplg_be_dev_type(mconfig->dev_type); 1557cfb0a873SVinod Koul 15588871dcb9SJeeja KP skl_tplg_fill_dma_id(mconfig, params); 1559cfb0a873SVinod Koul 1560b30c275eSJeeja KP if (link_type == NHLT_LINK_HDA) 1561b30c275eSJeeja KP return 0; 1562b30c275eSJeeja KP 1563cfb0a873SVinod Koul /* update the blob based on virtual bus_id*/ 1564cfb0a873SVinod Koul cfg = skl_get_ep_blob(skl, mconfig->vbus_id, link_type, 1565cfb0a873SVinod Koul params->s_fmt, params->ch, 1566db2f586bSSenthilnathan Veppur params->s_freq, params->stream, 1567db2f586bSSenthilnathan Veppur dev_type); 1568cfb0a873SVinod Koul if (cfg) { 1569cfb0a873SVinod Koul mconfig->formats_config.caps_size = cfg->size; 1570bc03281aSJeeja KP mconfig->formats_config.caps = (u32 *) &cfg->caps; 1571cfb0a873SVinod Koul } else { 1572cfb0a873SVinod Koul dev_err(dai->dev, "Blob NULL for id %x type %d dirn %d\n", 1573cfb0a873SVinod Koul mconfig->vbus_id, link_type, 1574cfb0a873SVinod Koul params->stream); 1575cfb0a873SVinod Koul dev_err(dai->dev, "PCM: ch %d, freq %d, fmt %d\n", 1576cfb0a873SVinod Koul params->ch, params->s_freq, params->s_fmt); 1577cfb0a873SVinod Koul return -EINVAL; 1578cfb0a873SVinod Koul } 1579cfb0a873SVinod Koul 1580cfb0a873SVinod Koul return 0; 1581cfb0a873SVinod Koul } 1582cfb0a873SVinod Koul 1583cfb0a873SVinod Koul static int skl_tplg_be_set_src_pipe_params(struct snd_soc_dai *dai, 1584cfb0a873SVinod Koul struct snd_soc_dapm_widget *w, 1585cfb0a873SVinod Koul struct skl_pipe_params *params) 1586cfb0a873SVinod Koul { 1587cfb0a873SVinod Koul struct snd_soc_dapm_path *p; 15884d8adccbSSubhransu S. Prusty int ret = -EIO; 1589cfb0a873SVinod Koul 1590f0900eb2SSubhransu S. Prusty snd_soc_dapm_widget_for_each_source_path(w, p) { 1591cfb0a873SVinod Koul if (p->connect && is_skl_dsp_widget_type(p->source) && 1592cfb0a873SVinod Koul p->source->priv) { 1593cfb0a873SVinod Koul 15949a03cb49SJeeja KP ret = skl_tplg_be_fill_pipe_params(dai, 15959a03cb49SJeeja KP p->source->priv, params); 15964d8adccbSSubhransu S. Prusty if (ret < 0) 15974d8adccbSSubhransu S. Prusty return ret; 1598cfb0a873SVinod Koul } else { 15999a03cb49SJeeja KP ret = skl_tplg_be_set_src_pipe_params(dai, 16009a03cb49SJeeja KP p->source, params); 16014d8adccbSSubhransu S. Prusty if (ret < 0) 16024d8adccbSSubhransu S. Prusty return ret; 1603cfb0a873SVinod Koul } 1604cfb0a873SVinod Koul } 1605cfb0a873SVinod Koul 16064d8adccbSSubhransu S. Prusty return ret; 1607cfb0a873SVinod Koul } 1608cfb0a873SVinod Koul 1609cfb0a873SVinod Koul static int skl_tplg_be_set_sink_pipe_params(struct snd_soc_dai *dai, 1610cfb0a873SVinod Koul struct snd_soc_dapm_widget *w, struct skl_pipe_params *params) 1611cfb0a873SVinod Koul { 1612cfb0a873SVinod Koul struct snd_soc_dapm_path *p = NULL; 16134d8adccbSSubhransu S. Prusty int ret = -EIO; 1614cfb0a873SVinod Koul 1615f0900eb2SSubhransu S. Prusty snd_soc_dapm_widget_for_each_sink_path(w, p) { 1616cfb0a873SVinod Koul if (p->connect && is_skl_dsp_widget_type(p->sink) && 1617cfb0a873SVinod Koul p->sink->priv) { 1618cfb0a873SVinod Koul 16199a03cb49SJeeja KP ret = skl_tplg_be_fill_pipe_params(dai, 16209a03cb49SJeeja KP p->sink->priv, params); 16214d8adccbSSubhransu S. Prusty if (ret < 0) 16224d8adccbSSubhransu S. Prusty return ret; 16234d8adccbSSubhransu S. Prusty } else { 16244d8adccbSSubhransu S. Prusty ret = skl_tplg_be_set_sink_pipe_params( 1625cfb0a873SVinod Koul dai, p->sink, params); 16264d8adccbSSubhransu S. Prusty if (ret < 0) 16274d8adccbSSubhransu S. Prusty return ret; 1628cfb0a873SVinod Koul } 1629cfb0a873SVinod Koul } 1630cfb0a873SVinod Koul 16314d8adccbSSubhransu S. Prusty return ret; 1632cfb0a873SVinod Koul } 1633cfb0a873SVinod Koul 1634cfb0a873SVinod Koul /* 1635cfb0a873SVinod Koul * BE hw_params can be a source parameters (capture) or sink parameters 1636cfb0a873SVinod Koul * (playback). Based on sink and source we need to either find the source 1637cfb0a873SVinod Koul * list or the sink list and set the pipeline parameters 1638cfb0a873SVinod Koul */ 1639cfb0a873SVinod Koul int skl_tplg_be_update_params(struct snd_soc_dai *dai, 1640cfb0a873SVinod Koul struct skl_pipe_params *params) 1641cfb0a873SVinod Koul { 1642cfb0a873SVinod Koul struct snd_soc_dapm_widget *w; 1643cfb0a873SVinod Koul 1644cfb0a873SVinod Koul if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) { 1645cfb0a873SVinod Koul w = dai->playback_widget; 1646cfb0a873SVinod Koul 1647cfb0a873SVinod Koul return skl_tplg_be_set_src_pipe_params(dai, w, params); 1648cfb0a873SVinod Koul 1649cfb0a873SVinod Koul } else { 1650cfb0a873SVinod Koul w = dai->capture_widget; 1651cfb0a873SVinod Koul 1652cfb0a873SVinod Koul return skl_tplg_be_set_sink_pipe_params(dai, w, params); 1653cfb0a873SVinod Koul } 1654cfb0a873SVinod Koul 1655cfb0a873SVinod Koul return 0; 1656cfb0a873SVinod Koul } 16573af36706SVinod Koul 16583af36706SVinod Koul static const struct snd_soc_tplg_widget_events skl_tplg_widget_ops[] = { 16593af36706SVinod Koul {SKL_MIXER_EVENT, skl_tplg_mixer_event}, 16609a1e3507SVinod Koul {SKL_VMIXER_EVENT, skl_tplg_mixer_event}, 16613af36706SVinod Koul {SKL_PGA_EVENT, skl_tplg_pga_event}, 16623af36706SVinod Koul }; 16633af36706SVinod Koul 1664140adfbaSJeeja KP static const struct snd_soc_tplg_bytes_ext_ops skl_tlv_ops[] = { 1665140adfbaSJeeja KP {SKL_CONTROL_TYPE_BYTE_TLV, skl_tplg_tlv_control_get, 1666140adfbaSJeeja KP skl_tplg_tlv_control_set}, 1667140adfbaSJeeja KP }; 1668140adfbaSJeeja KP 16696277e832SShreyas NC static int skl_tplg_fill_pipe_tkn(struct device *dev, 16706277e832SShreyas NC struct skl_pipe *pipe, u32 tkn, 16716277e832SShreyas NC u32 tkn_val) 16723af36706SVinod Koul { 16733af36706SVinod Koul 16746277e832SShreyas NC switch (tkn) { 16756277e832SShreyas NC case SKL_TKN_U32_PIPE_CONN_TYPE: 16766277e832SShreyas NC pipe->conn_type = tkn_val; 16776277e832SShreyas NC break; 16786277e832SShreyas NC 16796277e832SShreyas NC case SKL_TKN_U32_PIPE_PRIORITY: 16806277e832SShreyas NC pipe->pipe_priority = tkn_val; 16816277e832SShreyas NC break; 16826277e832SShreyas NC 16836277e832SShreyas NC case SKL_TKN_U32_PIPE_MEM_PGS: 16846277e832SShreyas NC pipe->memory_pages = tkn_val; 16856277e832SShreyas NC break; 16866277e832SShreyas NC 16878a0cb236SVinod Koul case SKL_TKN_U32_PMODE: 16888a0cb236SVinod Koul pipe->lp_mode = tkn_val; 16898a0cb236SVinod Koul break; 16908a0cb236SVinod Koul 16916277e832SShreyas NC default: 16926277e832SShreyas NC dev_err(dev, "Token not handled %d\n", tkn); 16936277e832SShreyas NC return -EINVAL; 16943af36706SVinod Koul } 16956277e832SShreyas NC 16966277e832SShreyas NC return 0; 16973af36706SVinod Koul } 16983af36706SVinod Koul 16993af36706SVinod Koul /* 17006277e832SShreyas NC * Add pipeline by parsing the relevant tokens 17016277e832SShreyas NC * Return an existing pipe if the pipe already exists. 17023af36706SVinod Koul */ 17036277e832SShreyas NC static int skl_tplg_add_pipe(struct device *dev, 17046277e832SShreyas NC struct skl_module_cfg *mconfig, struct skl *skl, 17056277e832SShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem) 17063af36706SVinod Koul { 17073af36706SVinod Koul struct skl_pipeline *ppl; 17083af36706SVinod Koul struct skl_pipe *pipe; 17093af36706SVinod Koul struct skl_pipe_params *params; 17103af36706SVinod Koul 17113af36706SVinod Koul list_for_each_entry(ppl, &skl->ppl_list, node) { 17126277e832SShreyas NC if (ppl->pipe->ppl_id == tkn_elem->value) { 17136277e832SShreyas NC mconfig->pipe = ppl->pipe; 17146277e832SShreyas NC return EEXIST; 17156277e832SShreyas NC } 17163af36706SVinod Koul } 17173af36706SVinod Koul 17183af36706SVinod Koul ppl = devm_kzalloc(dev, sizeof(*ppl), GFP_KERNEL); 17193af36706SVinod Koul if (!ppl) 17206277e832SShreyas NC return -ENOMEM; 17213af36706SVinod Koul 17223af36706SVinod Koul pipe = devm_kzalloc(dev, sizeof(*pipe), GFP_KERNEL); 17233af36706SVinod Koul if (!pipe) 17246277e832SShreyas NC return -ENOMEM; 17253af36706SVinod Koul 17263af36706SVinod Koul params = devm_kzalloc(dev, sizeof(*params), GFP_KERNEL); 17273af36706SVinod Koul if (!params) 17286277e832SShreyas NC return -ENOMEM; 17293af36706SVinod Koul 17303af36706SVinod Koul pipe->p_params = params; 17316277e832SShreyas NC pipe->ppl_id = tkn_elem->value; 17323af36706SVinod Koul INIT_LIST_HEAD(&pipe->w_list); 17333af36706SVinod Koul 17343af36706SVinod Koul ppl->pipe = pipe; 17353af36706SVinod Koul list_add(&ppl->node, &skl->ppl_list); 17363af36706SVinod Koul 17376277e832SShreyas NC mconfig->pipe = pipe; 17386277e832SShreyas NC mconfig->pipe->state = SKL_PIPE_INVALID; 17396277e832SShreyas NC 17406277e832SShreyas NC return 0; 17413af36706SVinod Koul } 17423af36706SVinod Koul 17436277e832SShreyas NC static int skl_tplg_fill_pin(struct device *dev, u32 tkn, 17446277e832SShreyas NC struct skl_module_pin *m_pin, 17456277e832SShreyas NC int pin_index, u32 value) 17466277e832SShreyas NC { 17476277e832SShreyas NC switch (tkn) { 17486277e832SShreyas NC case SKL_TKN_U32_PIN_MOD_ID: 17496277e832SShreyas NC m_pin[pin_index].id.module_id = value; 17506277e832SShreyas NC break; 17516277e832SShreyas NC 17526277e832SShreyas NC case SKL_TKN_U32_PIN_INST_ID: 17536277e832SShreyas NC m_pin[pin_index].id.instance_id = value; 17546277e832SShreyas NC break; 17556277e832SShreyas NC 17566277e832SShreyas NC default: 17576277e832SShreyas NC dev_err(dev, "%d Not a pin token\n", value); 17586277e832SShreyas NC return -EINVAL; 17596277e832SShreyas NC } 17606277e832SShreyas NC 17616277e832SShreyas NC return 0; 17626277e832SShreyas NC } 17636277e832SShreyas NC 17646277e832SShreyas NC /* 17656277e832SShreyas NC * Parse for pin config specific tokens to fill up the 17666277e832SShreyas NC * module private data 17676277e832SShreyas NC */ 17686277e832SShreyas NC static int skl_tplg_fill_pins_info(struct device *dev, 17696277e832SShreyas NC struct skl_module_cfg *mconfig, 17706277e832SShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem, 17716277e832SShreyas NC int dir, int pin_count) 17726277e832SShreyas NC { 17736277e832SShreyas NC int ret; 17746277e832SShreyas NC struct skl_module_pin *m_pin; 17756277e832SShreyas NC 17766277e832SShreyas NC switch (dir) { 17776277e832SShreyas NC case SKL_DIR_IN: 17786277e832SShreyas NC m_pin = mconfig->m_in_pin; 17796277e832SShreyas NC break; 17806277e832SShreyas NC 17816277e832SShreyas NC case SKL_DIR_OUT: 17826277e832SShreyas NC m_pin = mconfig->m_out_pin; 17836277e832SShreyas NC break; 17846277e832SShreyas NC 17856277e832SShreyas NC default: 1786ecd286a9SColin Ian King dev_err(dev, "Invalid direction value\n"); 17876277e832SShreyas NC return -EINVAL; 17886277e832SShreyas NC } 17896277e832SShreyas NC 17906277e832SShreyas NC ret = skl_tplg_fill_pin(dev, tkn_elem->token, 17916277e832SShreyas NC m_pin, pin_count, tkn_elem->value); 17926277e832SShreyas NC 17936277e832SShreyas NC if (ret < 0) 17946277e832SShreyas NC return ret; 17956277e832SShreyas NC 17966277e832SShreyas NC m_pin[pin_count].in_use = false; 17976277e832SShreyas NC m_pin[pin_count].pin_state = SKL_PIN_UNBIND; 17986277e832SShreyas NC 17996277e832SShreyas NC return 0; 18006277e832SShreyas NC } 18016277e832SShreyas NC 18026277e832SShreyas NC /* 18036277e832SShreyas NC * Fill up input/output module config format based 18046277e832SShreyas NC * on the direction 18056277e832SShreyas NC */ 18066277e832SShreyas NC static int skl_tplg_fill_fmt(struct device *dev, 18076277e832SShreyas NC struct skl_module_cfg *mconfig, u32 tkn, 18086277e832SShreyas NC u32 value, u32 dir, u32 pin_count) 18096277e832SShreyas NC { 18106277e832SShreyas NC struct skl_module_fmt *dst_fmt; 18116277e832SShreyas NC 18126277e832SShreyas NC switch (dir) { 18136277e832SShreyas NC case SKL_DIR_IN: 18146277e832SShreyas NC dst_fmt = mconfig->in_fmt; 18156277e832SShreyas NC dst_fmt += pin_count; 18166277e832SShreyas NC break; 18176277e832SShreyas NC 18186277e832SShreyas NC case SKL_DIR_OUT: 18196277e832SShreyas NC dst_fmt = mconfig->out_fmt; 18206277e832SShreyas NC dst_fmt += pin_count; 18216277e832SShreyas NC break; 18226277e832SShreyas NC 18236277e832SShreyas NC default: 1824ecd286a9SColin Ian King dev_err(dev, "Invalid direction value\n"); 18256277e832SShreyas NC return -EINVAL; 18266277e832SShreyas NC } 18276277e832SShreyas NC 18286277e832SShreyas NC switch (tkn) { 18296277e832SShreyas NC case SKL_TKN_U32_FMT_CH: 18306277e832SShreyas NC dst_fmt->channels = value; 18316277e832SShreyas NC break; 18326277e832SShreyas NC 18336277e832SShreyas NC case SKL_TKN_U32_FMT_FREQ: 18346277e832SShreyas NC dst_fmt->s_freq = value; 18356277e832SShreyas NC break; 18366277e832SShreyas NC 18376277e832SShreyas NC case SKL_TKN_U32_FMT_BIT_DEPTH: 18386277e832SShreyas NC dst_fmt->bit_depth = value; 18396277e832SShreyas NC break; 18406277e832SShreyas NC 18416277e832SShreyas NC case SKL_TKN_U32_FMT_SAMPLE_SIZE: 18426277e832SShreyas NC dst_fmt->valid_bit_depth = value; 18436277e832SShreyas NC break; 18446277e832SShreyas NC 18456277e832SShreyas NC case SKL_TKN_U32_FMT_CH_CONFIG: 18466277e832SShreyas NC dst_fmt->ch_cfg = value; 18476277e832SShreyas NC break; 18486277e832SShreyas NC 18496277e832SShreyas NC case SKL_TKN_U32_FMT_INTERLEAVE: 18506277e832SShreyas NC dst_fmt->interleaving_style = value; 18516277e832SShreyas NC break; 18526277e832SShreyas NC 18536277e832SShreyas NC case SKL_TKN_U32_FMT_SAMPLE_TYPE: 18546277e832SShreyas NC dst_fmt->sample_type = value; 18556277e832SShreyas NC break; 18566277e832SShreyas NC 18576277e832SShreyas NC case SKL_TKN_U32_FMT_CH_MAP: 18586277e832SShreyas NC dst_fmt->ch_map = value; 18596277e832SShreyas NC break; 18606277e832SShreyas NC 18616277e832SShreyas NC default: 1862ecd286a9SColin Ian King dev_err(dev, "Invalid token %d\n", tkn); 18636277e832SShreyas NC return -EINVAL; 18646277e832SShreyas NC } 18656277e832SShreyas NC 18666277e832SShreyas NC return 0; 18676277e832SShreyas NC } 18686277e832SShreyas NC 18696277e832SShreyas NC static int skl_tplg_get_uuid(struct device *dev, struct skl_module_cfg *mconfig, 18706277e832SShreyas NC struct snd_soc_tplg_vendor_uuid_elem *uuid_tkn) 18716277e832SShreyas NC { 18726277e832SShreyas NC if (uuid_tkn->token == SKL_TKN_UUID) 18736277e832SShreyas NC memcpy(&mconfig->guid, &uuid_tkn->uuid, 16); 18746277e832SShreyas NC else { 1875ecd286a9SColin Ian King dev_err(dev, "Not an UUID token tkn %d\n", uuid_tkn->token); 18766277e832SShreyas NC return -EINVAL; 18776277e832SShreyas NC } 18786277e832SShreyas NC 18796277e832SShreyas NC return 0; 18806277e832SShreyas NC } 18816277e832SShreyas NC 18826277e832SShreyas NC static void skl_tplg_fill_pin_dynamic_val( 18836277e832SShreyas NC struct skl_module_pin *mpin, u32 pin_count, u32 value) 18844cd9899fSHardik T Shah { 18854cd9899fSHardik T Shah int i; 18864cd9899fSHardik T Shah 18876277e832SShreyas NC for (i = 0; i < pin_count; i++) 18886277e832SShreyas NC mpin[i].is_dynamic = value; 18894cd9899fSHardik T Shah } 18906277e832SShreyas NC 18916277e832SShreyas NC /* 18926277e832SShreyas NC * Parse tokens to fill up the module private data 18936277e832SShreyas NC */ 18946277e832SShreyas NC static int skl_tplg_get_token(struct device *dev, 18956277e832SShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem, 18966277e832SShreyas NC struct skl *skl, struct skl_module_cfg *mconfig) 18976277e832SShreyas NC { 18986277e832SShreyas NC int tkn_count = 0; 18996277e832SShreyas NC int ret; 19006277e832SShreyas NC static int is_pipe_exists; 19016277e832SShreyas NC static int pin_index, dir; 19026277e832SShreyas NC 19036277e832SShreyas NC if (tkn_elem->token > SKL_TKN_MAX) 19046277e832SShreyas NC return -EINVAL; 19056277e832SShreyas NC 19066277e832SShreyas NC switch (tkn_elem->token) { 19076277e832SShreyas NC case SKL_TKN_U8_IN_QUEUE_COUNT: 19086277e832SShreyas NC mconfig->max_in_queue = tkn_elem->value; 19096277e832SShreyas NC mconfig->m_in_pin = devm_kzalloc(dev, mconfig->max_in_queue * 19106277e832SShreyas NC sizeof(*mconfig->m_in_pin), 19116277e832SShreyas NC GFP_KERNEL); 19126277e832SShreyas NC if (!mconfig->m_in_pin) 19136277e832SShreyas NC return -ENOMEM; 19146277e832SShreyas NC 19156277e832SShreyas NC break; 19166277e832SShreyas NC 19176277e832SShreyas NC case SKL_TKN_U8_OUT_QUEUE_COUNT: 19186277e832SShreyas NC mconfig->max_out_queue = tkn_elem->value; 19196277e832SShreyas NC mconfig->m_out_pin = devm_kzalloc(dev, mconfig->max_out_queue * 19206277e832SShreyas NC sizeof(*mconfig->m_out_pin), 19216277e832SShreyas NC GFP_KERNEL); 19226277e832SShreyas NC 19236277e832SShreyas NC if (!mconfig->m_out_pin) 19246277e832SShreyas NC return -ENOMEM; 19256277e832SShreyas NC 19266277e832SShreyas NC break; 19276277e832SShreyas NC 19286277e832SShreyas NC case SKL_TKN_U8_DYN_IN_PIN: 19296277e832SShreyas NC if (!mconfig->m_in_pin) 19306277e832SShreyas NC return -ENOMEM; 19316277e832SShreyas NC 19326277e832SShreyas NC skl_tplg_fill_pin_dynamic_val(mconfig->m_in_pin, 19336277e832SShreyas NC mconfig->max_in_queue, tkn_elem->value); 19346277e832SShreyas NC 19356277e832SShreyas NC break; 19366277e832SShreyas NC 19376277e832SShreyas NC case SKL_TKN_U8_DYN_OUT_PIN: 19386277e832SShreyas NC if (!mconfig->m_out_pin) 19396277e832SShreyas NC return -ENOMEM; 19406277e832SShreyas NC 19416277e832SShreyas NC skl_tplg_fill_pin_dynamic_val(mconfig->m_out_pin, 19426277e832SShreyas NC mconfig->max_out_queue, tkn_elem->value); 19436277e832SShreyas NC 19446277e832SShreyas NC break; 19456277e832SShreyas NC 19466277e832SShreyas NC case SKL_TKN_U8_TIME_SLOT: 19476277e832SShreyas NC mconfig->time_slot = tkn_elem->value; 19486277e832SShreyas NC break; 19496277e832SShreyas NC 19506277e832SShreyas NC case SKL_TKN_U8_CORE_ID: 19516277e832SShreyas NC mconfig->core_id = tkn_elem->value; 19526277e832SShreyas NC 19536277e832SShreyas NC case SKL_TKN_U8_MOD_TYPE: 19546277e832SShreyas NC mconfig->m_type = tkn_elem->value; 19556277e832SShreyas NC break; 19566277e832SShreyas NC 19576277e832SShreyas NC case SKL_TKN_U8_DEV_TYPE: 19586277e832SShreyas NC mconfig->dev_type = tkn_elem->value; 19596277e832SShreyas NC break; 19606277e832SShreyas NC 19616277e832SShreyas NC case SKL_TKN_U8_HW_CONN_TYPE: 19626277e832SShreyas NC mconfig->hw_conn_type = tkn_elem->value; 19636277e832SShreyas NC break; 19646277e832SShreyas NC 19656277e832SShreyas NC case SKL_TKN_U16_MOD_INST_ID: 19666277e832SShreyas NC mconfig->id.instance_id = 19676277e832SShreyas NC tkn_elem->value; 19686277e832SShreyas NC break; 19696277e832SShreyas NC 19706277e832SShreyas NC case SKL_TKN_U32_MEM_PAGES: 19716277e832SShreyas NC mconfig->mem_pages = tkn_elem->value; 19726277e832SShreyas NC break; 19736277e832SShreyas NC 19746277e832SShreyas NC case SKL_TKN_U32_MAX_MCPS: 19756277e832SShreyas NC mconfig->mcps = tkn_elem->value; 19766277e832SShreyas NC break; 19776277e832SShreyas NC 19786277e832SShreyas NC case SKL_TKN_U32_OBS: 19796277e832SShreyas NC mconfig->obs = tkn_elem->value; 19806277e832SShreyas NC break; 19816277e832SShreyas NC 19826277e832SShreyas NC case SKL_TKN_U32_IBS: 19836277e832SShreyas NC mconfig->ibs = tkn_elem->value; 19846277e832SShreyas NC break; 19856277e832SShreyas NC 19866277e832SShreyas NC case SKL_TKN_U32_VBUS_ID: 19876277e832SShreyas NC mconfig->vbus_id = tkn_elem->value; 19886277e832SShreyas NC break; 19896277e832SShreyas NC 19906277e832SShreyas NC case SKL_TKN_U32_PARAMS_FIXUP: 19916277e832SShreyas NC mconfig->params_fixup = tkn_elem->value; 19926277e832SShreyas NC break; 19936277e832SShreyas NC 19946277e832SShreyas NC case SKL_TKN_U32_CONVERTER: 19956277e832SShreyas NC mconfig->converter = tkn_elem->value; 19966277e832SShreyas NC break; 19976277e832SShreyas NC 19986bd9dcf3SVinod Koul case SKL_TKL_U32_D0I3_CAPS: 19996bd9dcf3SVinod Koul mconfig->d0i3_caps = tkn_elem->value; 20006bd9dcf3SVinod Koul break; 20016bd9dcf3SVinod Koul 20026277e832SShreyas NC case SKL_TKN_U32_PIPE_ID: 20036277e832SShreyas NC ret = skl_tplg_add_pipe(dev, 20046277e832SShreyas NC mconfig, skl, tkn_elem); 20056277e832SShreyas NC 20066277e832SShreyas NC if (ret < 0) 20076277e832SShreyas NC return is_pipe_exists; 20086277e832SShreyas NC 20096277e832SShreyas NC if (ret == EEXIST) 20106277e832SShreyas NC is_pipe_exists = 1; 20116277e832SShreyas NC 20126277e832SShreyas NC break; 20136277e832SShreyas NC 20146277e832SShreyas NC case SKL_TKN_U32_PIPE_CONN_TYPE: 20156277e832SShreyas NC case SKL_TKN_U32_PIPE_PRIORITY: 20166277e832SShreyas NC case SKL_TKN_U32_PIPE_MEM_PGS: 20178a0cb236SVinod Koul case SKL_TKN_U32_PMODE: 20186277e832SShreyas NC if (is_pipe_exists) { 20196277e832SShreyas NC ret = skl_tplg_fill_pipe_tkn(dev, mconfig->pipe, 20206277e832SShreyas NC tkn_elem->token, tkn_elem->value); 20216277e832SShreyas NC if (ret < 0) 20226277e832SShreyas NC return ret; 20236277e832SShreyas NC } 20246277e832SShreyas NC 20256277e832SShreyas NC break; 20266277e832SShreyas NC 20276277e832SShreyas NC /* 20286277e832SShreyas NC * SKL_TKN_U32_DIR_PIN_COUNT token has the value for both 20296277e832SShreyas NC * direction and the pin count. The first four bits represent 20306277e832SShreyas NC * direction and next four the pin count. 20316277e832SShreyas NC */ 20326277e832SShreyas NC case SKL_TKN_U32_DIR_PIN_COUNT: 20336277e832SShreyas NC dir = tkn_elem->value & SKL_IN_DIR_BIT_MASK; 20346277e832SShreyas NC pin_index = (tkn_elem->value & 20356277e832SShreyas NC SKL_PIN_COUNT_MASK) >> 4; 20366277e832SShreyas NC 20376277e832SShreyas NC break; 20386277e832SShreyas NC 20396277e832SShreyas NC case SKL_TKN_U32_FMT_CH: 20406277e832SShreyas NC case SKL_TKN_U32_FMT_FREQ: 20416277e832SShreyas NC case SKL_TKN_U32_FMT_BIT_DEPTH: 20426277e832SShreyas NC case SKL_TKN_U32_FMT_SAMPLE_SIZE: 20436277e832SShreyas NC case SKL_TKN_U32_FMT_CH_CONFIG: 20446277e832SShreyas NC case SKL_TKN_U32_FMT_INTERLEAVE: 20456277e832SShreyas NC case SKL_TKN_U32_FMT_SAMPLE_TYPE: 20466277e832SShreyas NC case SKL_TKN_U32_FMT_CH_MAP: 20476277e832SShreyas NC ret = skl_tplg_fill_fmt(dev, mconfig, tkn_elem->token, 20486277e832SShreyas NC tkn_elem->value, dir, pin_index); 20496277e832SShreyas NC 20506277e832SShreyas NC if (ret < 0) 20516277e832SShreyas NC return ret; 20526277e832SShreyas NC 20536277e832SShreyas NC break; 20546277e832SShreyas NC 20556277e832SShreyas NC case SKL_TKN_U32_PIN_MOD_ID: 20566277e832SShreyas NC case SKL_TKN_U32_PIN_INST_ID: 20576277e832SShreyas NC ret = skl_tplg_fill_pins_info(dev, 20586277e832SShreyas NC mconfig, tkn_elem, dir, 20596277e832SShreyas NC pin_index); 20606277e832SShreyas NC if (ret < 0) 20616277e832SShreyas NC return ret; 20626277e832SShreyas NC 20636277e832SShreyas NC break; 20646277e832SShreyas NC 20656277e832SShreyas NC case SKL_TKN_U32_CAPS_SIZE: 20666277e832SShreyas NC mconfig->formats_config.caps_size = 20676277e832SShreyas NC tkn_elem->value; 20686277e832SShreyas NC 20696277e832SShreyas NC break; 20706277e832SShreyas NC 20716277e832SShreyas NC case SKL_TKN_U32_PROC_DOMAIN: 20726277e832SShreyas NC mconfig->domain = 20736277e832SShreyas NC tkn_elem->value; 20746277e832SShreyas NC 20756277e832SShreyas NC break; 20766277e832SShreyas NC 20776277e832SShreyas NC case SKL_TKN_U8_IN_PIN_TYPE: 20786277e832SShreyas NC case SKL_TKN_U8_OUT_PIN_TYPE: 20796277e832SShreyas NC case SKL_TKN_U8_CONN_TYPE: 20806277e832SShreyas NC break; 20816277e832SShreyas NC 20826277e832SShreyas NC default: 20836277e832SShreyas NC dev_err(dev, "Token %d not handled\n", 20846277e832SShreyas NC tkn_elem->token); 20856277e832SShreyas NC return -EINVAL; 20866277e832SShreyas NC } 20876277e832SShreyas NC 20886277e832SShreyas NC tkn_count++; 20896277e832SShreyas NC 20906277e832SShreyas NC return tkn_count; 20916277e832SShreyas NC } 20926277e832SShreyas NC 20936277e832SShreyas NC /* 20946277e832SShreyas NC * Parse the vendor array for specific tokens to construct 20956277e832SShreyas NC * module private data 20966277e832SShreyas NC */ 20976277e832SShreyas NC static int skl_tplg_get_tokens(struct device *dev, 20986277e832SShreyas NC char *pvt_data, struct skl *skl, 20996277e832SShreyas NC struct skl_module_cfg *mconfig, int block_size) 21006277e832SShreyas NC { 21016277e832SShreyas NC struct snd_soc_tplg_vendor_array *array; 21026277e832SShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem; 21036277e832SShreyas NC int tkn_count = 0, ret; 21046277e832SShreyas NC int off = 0, tuple_size = 0; 21056277e832SShreyas NC 21066277e832SShreyas NC if (block_size <= 0) 21076277e832SShreyas NC return -EINVAL; 21086277e832SShreyas NC 21096277e832SShreyas NC while (tuple_size < block_size) { 21106277e832SShreyas NC array = (struct snd_soc_tplg_vendor_array *)(pvt_data + off); 21116277e832SShreyas NC 21126277e832SShreyas NC off += array->size; 21136277e832SShreyas NC 21146277e832SShreyas NC switch (array->type) { 21156277e832SShreyas NC case SND_SOC_TPLG_TUPLE_TYPE_STRING: 2116ecd286a9SColin Ian King dev_warn(dev, "no string tokens expected for skl tplg\n"); 21176277e832SShreyas NC continue; 21186277e832SShreyas NC 21196277e832SShreyas NC case SND_SOC_TPLG_TUPLE_TYPE_UUID: 21206277e832SShreyas NC ret = skl_tplg_get_uuid(dev, mconfig, array->uuid); 21216277e832SShreyas NC if (ret < 0) 21226277e832SShreyas NC return ret; 21236277e832SShreyas NC 21246277e832SShreyas NC tuple_size += sizeof(*array->uuid); 21256277e832SShreyas NC 21266277e832SShreyas NC continue; 21276277e832SShreyas NC 21286277e832SShreyas NC default: 21296277e832SShreyas NC tkn_elem = array->value; 21306277e832SShreyas NC tkn_count = 0; 21316277e832SShreyas NC break; 21326277e832SShreyas NC } 21336277e832SShreyas NC 21346277e832SShreyas NC while (tkn_count <= (array->num_elems - 1)) { 21356277e832SShreyas NC ret = skl_tplg_get_token(dev, tkn_elem, 21366277e832SShreyas NC skl, mconfig); 21376277e832SShreyas NC 21386277e832SShreyas NC if (ret < 0) 21396277e832SShreyas NC return ret; 21406277e832SShreyas NC 21416277e832SShreyas NC tkn_count = tkn_count + ret; 21426277e832SShreyas NC tkn_elem++; 21436277e832SShreyas NC } 21446277e832SShreyas NC 21456277e832SShreyas NC tuple_size += tkn_count * sizeof(*tkn_elem); 21466277e832SShreyas NC } 21476277e832SShreyas NC 21486277e832SShreyas NC return 0; 21496277e832SShreyas NC } 21506277e832SShreyas NC 21516277e832SShreyas NC /* 21526277e832SShreyas NC * Every data block is preceded by a descriptor to read the number 21536277e832SShreyas NC * of data blocks, they type of the block and it's size 21546277e832SShreyas NC */ 21556277e832SShreyas NC static int skl_tplg_get_desc_blocks(struct device *dev, 21566277e832SShreyas NC struct snd_soc_tplg_vendor_array *array) 21576277e832SShreyas NC { 21586277e832SShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem; 21596277e832SShreyas NC 21606277e832SShreyas NC tkn_elem = array->value; 21616277e832SShreyas NC 21626277e832SShreyas NC switch (tkn_elem->token) { 21636277e832SShreyas NC case SKL_TKN_U8_NUM_BLOCKS: 21646277e832SShreyas NC case SKL_TKN_U8_BLOCK_TYPE: 21656277e832SShreyas NC case SKL_TKN_U16_BLOCK_SIZE: 21666277e832SShreyas NC return tkn_elem->value; 21676277e832SShreyas NC 21686277e832SShreyas NC default: 2169ecd286a9SColin Ian King dev_err(dev, "Invalid descriptor token %d\n", tkn_elem->token); 21706277e832SShreyas NC break; 21716277e832SShreyas NC } 21726277e832SShreyas NC 21736277e832SShreyas NC return -EINVAL; 21746277e832SShreyas NC } 21756277e832SShreyas NC 21766277e832SShreyas NC /* 21776277e832SShreyas NC * Parse the private data for the token and corresponding value. 21786277e832SShreyas NC * The private data can have multiple data blocks. So, a data block 21796277e832SShreyas NC * is preceded by a descriptor for number of blocks and a descriptor 21806277e832SShreyas NC * for the type and size of the suceeding data block. 21816277e832SShreyas NC */ 21826277e832SShreyas NC static int skl_tplg_get_pvt_data(struct snd_soc_tplg_dapm_widget *tplg_w, 21836277e832SShreyas NC struct skl *skl, struct device *dev, 21846277e832SShreyas NC struct skl_module_cfg *mconfig) 21856277e832SShreyas NC { 21866277e832SShreyas NC struct snd_soc_tplg_vendor_array *array; 21876277e832SShreyas NC int num_blocks, block_size = 0, block_type, off = 0; 21886277e832SShreyas NC char *data; 21896277e832SShreyas NC int ret; 21906277e832SShreyas NC 21916277e832SShreyas NC /* Read the NUM_DATA_BLOCKS descriptor */ 21926277e832SShreyas NC array = (struct snd_soc_tplg_vendor_array *)tplg_w->priv.data; 21936277e832SShreyas NC ret = skl_tplg_get_desc_blocks(dev, array); 21946277e832SShreyas NC if (ret < 0) 21956277e832SShreyas NC return ret; 21966277e832SShreyas NC num_blocks = ret; 21976277e832SShreyas NC 21986277e832SShreyas NC off += array->size; 21996277e832SShreyas NC array = (struct snd_soc_tplg_vendor_array *)(tplg_w->priv.data + off); 22006277e832SShreyas NC 22016277e832SShreyas NC /* Read the BLOCK_TYPE and BLOCK_SIZE descriptor */ 22026277e832SShreyas NC while (num_blocks > 0) { 22036277e832SShreyas NC ret = skl_tplg_get_desc_blocks(dev, array); 22046277e832SShreyas NC 22056277e832SShreyas NC if (ret < 0) 22066277e832SShreyas NC return ret; 22076277e832SShreyas NC block_type = ret; 22086277e832SShreyas NC off += array->size; 22096277e832SShreyas NC 22106277e832SShreyas NC array = (struct snd_soc_tplg_vendor_array *) 22116277e832SShreyas NC (tplg_w->priv.data + off); 22126277e832SShreyas NC 22136277e832SShreyas NC ret = skl_tplg_get_desc_blocks(dev, array); 22146277e832SShreyas NC 22156277e832SShreyas NC if (ret < 0) 22166277e832SShreyas NC return ret; 22176277e832SShreyas NC block_size = ret; 22186277e832SShreyas NC off += array->size; 22196277e832SShreyas NC 22206277e832SShreyas NC array = (struct snd_soc_tplg_vendor_array *) 22216277e832SShreyas NC (tplg_w->priv.data + off); 22226277e832SShreyas NC 22236277e832SShreyas NC data = (tplg_w->priv.data + off); 22246277e832SShreyas NC 22256277e832SShreyas NC if (block_type == SKL_TYPE_TUPLE) { 22266277e832SShreyas NC ret = skl_tplg_get_tokens(dev, data, 22276277e832SShreyas NC skl, mconfig, block_size); 22286277e832SShreyas NC 22296277e832SShreyas NC if (ret < 0) 22306277e832SShreyas NC return ret; 22316277e832SShreyas NC 22326277e832SShreyas NC --num_blocks; 22336277e832SShreyas NC } else { 22346277e832SShreyas NC if (mconfig->formats_config.caps_size > 0) 22356277e832SShreyas NC memcpy(mconfig->formats_config.caps, data, 22366277e832SShreyas NC mconfig->formats_config.caps_size); 22376277e832SShreyas NC --num_blocks; 22386277e832SShreyas NC } 22396277e832SShreyas NC } 22406277e832SShreyas NC 22416277e832SShreyas NC return 0; 22424cd9899fSHardik T Shah } 22434cd9899fSHardik T Shah 2244fe3f4442SDharageswari R static void skl_clear_pin_config(struct snd_soc_platform *platform, 2245fe3f4442SDharageswari R struct snd_soc_dapm_widget *w) 2246fe3f4442SDharageswari R { 2247fe3f4442SDharageswari R int i; 2248fe3f4442SDharageswari R struct skl_module_cfg *mconfig; 2249fe3f4442SDharageswari R struct skl_pipe *pipe; 2250fe3f4442SDharageswari R 2251fe3f4442SDharageswari R if (!strncmp(w->dapm->component->name, platform->component.name, 2252fe3f4442SDharageswari R strlen(platform->component.name))) { 2253fe3f4442SDharageswari R mconfig = w->priv; 2254fe3f4442SDharageswari R pipe = mconfig->pipe; 2255fe3f4442SDharageswari R for (i = 0; i < mconfig->max_in_queue; i++) { 2256fe3f4442SDharageswari R mconfig->m_in_pin[i].in_use = false; 2257fe3f4442SDharageswari R mconfig->m_in_pin[i].pin_state = SKL_PIN_UNBIND; 2258fe3f4442SDharageswari R } 2259fe3f4442SDharageswari R for (i = 0; i < mconfig->max_out_queue; i++) { 2260fe3f4442SDharageswari R mconfig->m_out_pin[i].in_use = false; 2261fe3f4442SDharageswari R mconfig->m_out_pin[i].pin_state = SKL_PIN_UNBIND; 2262fe3f4442SDharageswari R } 2263fe3f4442SDharageswari R pipe->state = SKL_PIPE_INVALID; 2264fe3f4442SDharageswari R mconfig->m_state = SKL_MODULE_UNINIT; 2265fe3f4442SDharageswari R } 2266fe3f4442SDharageswari R } 2267fe3f4442SDharageswari R 2268fe3f4442SDharageswari R void skl_cleanup_resources(struct skl *skl) 2269fe3f4442SDharageswari R { 2270fe3f4442SDharageswari R struct skl_sst *ctx = skl->skl_sst; 2271fe3f4442SDharageswari R struct snd_soc_platform *soc_platform = skl->platform; 2272fe3f4442SDharageswari R struct snd_soc_dapm_widget *w; 2273fe3f4442SDharageswari R struct snd_soc_card *card; 2274fe3f4442SDharageswari R 2275fe3f4442SDharageswari R if (soc_platform == NULL) 2276fe3f4442SDharageswari R return; 2277fe3f4442SDharageswari R 2278fe3f4442SDharageswari R card = soc_platform->component.card; 2279fe3f4442SDharageswari R if (!card || !card->instantiated) 2280fe3f4442SDharageswari R return; 2281fe3f4442SDharageswari R 2282fe3f4442SDharageswari R skl->resource.mem = 0; 2283fe3f4442SDharageswari R skl->resource.mcps = 0; 2284fe3f4442SDharageswari R 2285fe3f4442SDharageswari R list_for_each_entry(w, &card->widgets, list) { 2286fe3f4442SDharageswari R if (is_skl_dsp_widget_type(w) && (w->priv != NULL)) 2287fe3f4442SDharageswari R skl_clear_pin_config(soc_platform, w); 2288fe3f4442SDharageswari R } 2289fe3f4442SDharageswari R 2290fe3f4442SDharageswari R skl_clear_module_cnt(ctx->dsp); 2291fe3f4442SDharageswari R } 2292fe3f4442SDharageswari R 22933af36706SVinod Koul /* 22943af36706SVinod Koul * Topology core widget load callback 22953af36706SVinod Koul * 22963af36706SVinod Koul * This is used to save the private data for each widget which gives 22973af36706SVinod Koul * information to the driver about module and pipeline parameters which DSP 22983af36706SVinod Koul * FW expects like ids, resource values, formats etc 22993af36706SVinod Koul */ 23003af36706SVinod Koul static int skl_tplg_widget_load(struct snd_soc_component *cmpnt, 23013af36706SVinod Koul struct snd_soc_dapm_widget *w, 23023af36706SVinod Koul struct snd_soc_tplg_dapm_widget *tplg_w) 23033af36706SVinod Koul { 23043af36706SVinod Koul int ret; 23053af36706SVinod Koul struct hdac_ext_bus *ebus = snd_soc_component_get_drvdata(cmpnt); 23063af36706SVinod Koul struct skl *skl = ebus_to_skl(ebus); 23073af36706SVinod Koul struct hdac_bus *bus = ebus_to_hbus(ebus); 23083af36706SVinod Koul struct skl_module_cfg *mconfig; 23093af36706SVinod Koul 23103af36706SVinod Koul if (!tplg_w->priv.size) 23113af36706SVinod Koul goto bind_event; 23123af36706SVinod Koul 23133af36706SVinod Koul mconfig = devm_kzalloc(bus->dev, sizeof(*mconfig), GFP_KERNEL); 23143af36706SVinod Koul 23153af36706SVinod Koul if (!mconfig) 23163af36706SVinod Koul return -ENOMEM; 23173af36706SVinod Koul 23183af36706SVinod Koul w->priv = mconfig; 231909305da9SShreyas NC 2320b7c50555SVinod Koul /* 2321b7c50555SVinod Koul * module binary can be loaded later, so set it to query when 2322b7c50555SVinod Koul * module is load for a use case 2323b7c50555SVinod Koul */ 2324b7c50555SVinod Koul mconfig->id.module_id = -1; 23254cd9899fSHardik T Shah 23266277e832SShreyas NC /* Parse private data for tuples */ 23276277e832SShreyas NC ret = skl_tplg_get_pvt_data(tplg_w, skl, bus->dev, mconfig); 23286277e832SShreyas NC if (ret < 0) 23296277e832SShreyas NC return ret; 23303af36706SVinod Koul bind_event: 23313af36706SVinod Koul if (tplg_w->event_type == 0) { 23323373f716SVinod Koul dev_dbg(bus->dev, "ASoC: No event handler required\n"); 23333af36706SVinod Koul return 0; 23343af36706SVinod Koul } 23353af36706SVinod Koul 23363af36706SVinod Koul ret = snd_soc_tplg_widget_bind_event(w, skl_tplg_widget_ops, 2337b663a8c5SJeeja KP ARRAY_SIZE(skl_tplg_widget_ops), 2338b663a8c5SJeeja KP tplg_w->event_type); 23393af36706SVinod Koul 23403af36706SVinod Koul if (ret) { 23413af36706SVinod Koul dev_err(bus->dev, "%s: No matching event handlers found for %d\n", 23423af36706SVinod Koul __func__, tplg_w->event_type); 23433af36706SVinod Koul return -EINVAL; 23443af36706SVinod Koul } 23453af36706SVinod Koul 23463af36706SVinod Koul return 0; 23473af36706SVinod Koul } 23483af36706SVinod Koul 2349140adfbaSJeeja KP static int skl_init_algo_data(struct device *dev, struct soc_bytes_ext *be, 2350140adfbaSJeeja KP struct snd_soc_tplg_bytes_control *bc) 2351140adfbaSJeeja KP { 2352140adfbaSJeeja KP struct skl_algo_data *ac; 2353140adfbaSJeeja KP struct skl_dfw_algo_data *dfw_ac = 2354140adfbaSJeeja KP (struct skl_dfw_algo_data *)bc->priv.data; 2355140adfbaSJeeja KP 2356140adfbaSJeeja KP ac = devm_kzalloc(dev, sizeof(*ac), GFP_KERNEL); 2357140adfbaSJeeja KP if (!ac) 2358140adfbaSJeeja KP return -ENOMEM; 2359140adfbaSJeeja KP 2360140adfbaSJeeja KP /* Fill private data */ 2361140adfbaSJeeja KP ac->max = dfw_ac->max; 2362140adfbaSJeeja KP ac->param_id = dfw_ac->param_id; 2363140adfbaSJeeja KP ac->set_params = dfw_ac->set_params; 23640d682104SDharageswari R ac->size = dfw_ac->max; 2365140adfbaSJeeja KP 2366140adfbaSJeeja KP if (ac->max) { 2367140adfbaSJeeja KP ac->params = (char *) devm_kzalloc(dev, ac->max, GFP_KERNEL); 2368140adfbaSJeeja KP if (!ac->params) 2369140adfbaSJeeja KP return -ENOMEM; 2370140adfbaSJeeja KP 2371140adfbaSJeeja KP memcpy(ac->params, dfw_ac->params, ac->max); 2372140adfbaSJeeja KP } 2373140adfbaSJeeja KP 2374140adfbaSJeeja KP be->dobj.private = ac; 2375140adfbaSJeeja KP return 0; 2376140adfbaSJeeja KP } 2377140adfbaSJeeja KP 2378140adfbaSJeeja KP static int skl_tplg_control_load(struct snd_soc_component *cmpnt, 2379140adfbaSJeeja KP struct snd_kcontrol_new *kctl, 2380140adfbaSJeeja KP struct snd_soc_tplg_ctl_hdr *hdr) 2381140adfbaSJeeja KP { 2382140adfbaSJeeja KP struct soc_bytes_ext *sb; 2383140adfbaSJeeja KP struct snd_soc_tplg_bytes_control *tplg_bc; 2384140adfbaSJeeja KP struct hdac_ext_bus *ebus = snd_soc_component_get_drvdata(cmpnt); 2385140adfbaSJeeja KP struct hdac_bus *bus = ebus_to_hbus(ebus); 2386140adfbaSJeeja KP 2387140adfbaSJeeja KP switch (hdr->ops.info) { 2388140adfbaSJeeja KP case SND_SOC_TPLG_CTL_BYTES: 2389140adfbaSJeeja KP tplg_bc = container_of(hdr, 2390140adfbaSJeeja KP struct snd_soc_tplg_bytes_control, hdr); 2391140adfbaSJeeja KP if (kctl->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { 2392140adfbaSJeeja KP sb = (struct soc_bytes_ext *)kctl->private_value; 2393140adfbaSJeeja KP if (tplg_bc->priv.size) 2394140adfbaSJeeja KP return skl_init_algo_data( 2395140adfbaSJeeja KP bus->dev, sb, tplg_bc); 2396140adfbaSJeeja KP } 2397140adfbaSJeeja KP break; 2398140adfbaSJeeja KP 2399140adfbaSJeeja KP default: 2400140adfbaSJeeja KP dev_warn(bus->dev, "Control load not supported %d:%d:%d\n", 2401140adfbaSJeeja KP hdr->ops.get, hdr->ops.put, hdr->ops.info); 2402140adfbaSJeeja KP break; 2403140adfbaSJeeja KP } 2404140adfbaSJeeja KP 2405140adfbaSJeeja KP return 0; 2406140adfbaSJeeja KP } 2407140adfbaSJeeja KP 2408541070ceSShreyas NC static int skl_tplg_fill_str_mfest_tkn(struct device *dev, 2409541070ceSShreyas NC struct snd_soc_tplg_vendor_string_elem *str_elem, 2410eee0e16fSJeeja KP struct skl *skl) 2411541070ceSShreyas NC { 2412541070ceSShreyas NC int tkn_count = 0; 2413541070ceSShreyas NC static int ref_count; 2414541070ceSShreyas NC 2415541070ceSShreyas NC switch (str_elem->token) { 2416541070ceSShreyas NC case SKL_TKN_STR_LIB_NAME: 2417eee0e16fSJeeja KP if (ref_count > skl->skl_sst->lib_count - 1) { 2418541070ceSShreyas NC ref_count = 0; 2419541070ceSShreyas NC return -EINVAL; 2420541070ceSShreyas NC } 2421541070ceSShreyas NC 2422eee0e16fSJeeja KP strncpy(skl->skl_sst->lib_info[ref_count].name, 2423eee0e16fSJeeja KP str_elem->string, 2424eee0e16fSJeeja KP ARRAY_SIZE(skl->skl_sst->lib_info[ref_count].name)); 2425541070ceSShreyas NC ref_count++; 2426541070ceSShreyas NC tkn_count++; 2427541070ceSShreyas NC break; 2428541070ceSShreyas NC 2429541070ceSShreyas NC default: 2430ecd286a9SColin Ian King dev_err(dev, "Not a string token %d\n", str_elem->token); 2431541070ceSShreyas NC break; 2432541070ceSShreyas NC } 2433541070ceSShreyas NC 2434541070ceSShreyas NC return tkn_count; 2435541070ceSShreyas NC } 2436541070ceSShreyas NC 2437541070ceSShreyas NC static int skl_tplg_get_str_tkn(struct device *dev, 2438541070ceSShreyas NC struct snd_soc_tplg_vendor_array *array, 2439eee0e16fSJeeja KP struct skl *skl) 2440541070ceSShreyas NC { 2441541070ceSShreyas NC int tkn_count = 0, ret; 2442541070ceSShreyas NC struct snd_soc_tplg_vendor_string_elem *str_elem; 2443541070ceSShreyas NC 2444541070ceSShreyas NC str_elem = (struct snd_soc_tplg_vendor_string_elem *)array->value; 2445541070ceSShreyas NC while (tkn_count < array->num_elems) { 2446eee0e16fSJeeja KP ret = skl_tplg_fill_str_mfest_tkn(dev, str_elem, skl); 2447541070ceSShreyas NC str_elem++; 2448541070ceSShreyas NC 2449541070ceSShreyas NC if (ret < 0) 2450541070ceSShreyas NC return ret; 2451541070ceSShreyas NC 2452541070ceSShreyas NC tkn_count = tkn_count + ret; 2453541070ceSShreyas NC } 2454541070ceSShreyas NC 2455541070ceSShreyas NC return tkn_count; 2456541070ceSShreyas NC } 2457541070ceSShreyas NC 2458541070ceSShreyas NC static int skl_tplg_get_int_tkn(struct device *dev, 2459541070ceSShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem, 2460eee0e16fSJeeja KP struct skl *skl) 2461541070ceSShreyas NC { 2462541070ceSShreyas NC int tkn_count = 0; 2463541070ceSShreyas NC 2464541070ceSShreyas NC switch (tkn_elem->token) { 2465541070ceSShreyas NC case SKL_TKN_U32_LIB_COUNT: 2466eee0e16fSJeeja KP skl->skl_sst->lib_count = tkn_elem->value; 2467541070ceSShreyas NC tkn_count++; 2468541070ceSShreyas NC break; 2469541070ceSShreyas NC 2470541070ceSShreyas NC default: 2471ecd286a9SColin Ian King dev_err(dev, "Not a manifest token %d\n", tkn_elem->token); 2472541070ceSShreyas NC return -EINVAL; 2473541070ceSShreyas NC } 2474541070ceSShreyas NC 2475541070ceSShreyas NC return tkn_count; 2476541070ceSShreyas NC } 2477541070ceSShreyas NC 2478541070ceSShreyas NC /* 2479541070ceSShreyas NC * Fill the manifest structure by parsing the tokens based on the 2480541070ceSShreyas NC * type. 2481541070ceSShreyas NC */ 2482541070ceSShreyas NC static int skl_tplg_get_manifest_tkn(struct device *dev, 2483eee0e16fSJeeja KP char *pvt_data, struct skl *skl, 2484541070ceSShreyas NC int block_size) 2485541070ceSShreyas NC { 2486541070ceSShreyas NC int tkn_count = 0, ret; 2487541070ceSShreyas NC int off = 0, tuple_size = 0; 2488541070ceSShreyas NC struct snd_soc_tplg_vendor_array *array; 2489541070ceSShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem; 2490541070ceSShreyas NC 2491541070ceSShreyas NC if (block_size <= 0) 2492541070ceSShreyas NC return -EINVAL; 2493541070ceSShreyas NC 2494541070ceSShreyas NC while (tuple_size < block_size) { 2495541070ceSShreyas NC array = (struct snd_soc_tplg_vendor_array *)(pvt_data + off); 2496541070ceSShreyas NC off += array->size; 2497541070ceSShreyas NC switch (array->type) { 2498541070ceSShreyas NC case SND_SOC_TPLG_TUPLE_TYPE_STRING: 2499eee0e16fSJeeja KP ret = skl_tplg_get_str_tkn(dev, array, skl); 2500541070ceSShreyas NC 2501541070ceSShreyas NC if (ret < 0) 2502541070ceSShreyas NC return ret; 2503541070ceSShreyas NC tkn_count += ret; 2504541070ceSShreyas NC 2505541070ceSShreyas NC tuple_size += tkn_count * 2506541070ceSShreyas NC sizeof(struct snd_soc_tplg_vendor_string_elem); 2507541070ceSShreyas NC continue; 2508541070ceSShreyas NC 2509541070ceSShreyas NC case SND_SOC_TPLG_TUPLE_TYPE_UUID: 2510ecd286a9SColin Ian King dev_warn(dev, "no uuid tokens for skl tplf manifest\n"); 2511541070ceSShreyas NC continue; 2512541070ceSShreyas NC 2513541070ceSShreyas NC default: 2514541070ceSShreyas NC tkn_elem = array->value; 2515541070ceSShreyas NC tkn_count = 0; 2516541070ceSShreyas NC break; 2517541070ceSShreyas NC } 2518541070ceSShreyas NC 2519541070ceSShreyas NC while (tkn_count <= array->num_elems - 1) { 2520541070ceSShreyas NC ret = skl_tplg_get_int_tkn(dev, 2521eee0e16fSJeeja KP tkn_elem, skl); 2522541070ceSShreyas NC if (ret < 0) 2523541070ceSShreyas NC return ret; 2524541070ceSShreyas NC 2525541070ceSShreyas NC tkn_count = tkn_count + ret; 2526541070ceSShreyas NC tkn_elem++; 2527541070ceSShreyas NC tuple_size += tkn_count * 2528541070ceSShreyas NC sizeof(struct snd_soc_tplg_vendor_value_elem); 2529541070ceSShreyas NC break; 2530541070ceSShreyas NC } 2531541070ceSShreyas NC tkn_count = 0; 2532541070ceSShreyas NC } 2533541070ceSShreyas NC 2534541070ceSShreyas NC return 0; 2535541070ceSShreyas NC } 2536541070ceSShreyas NC 2537541070ceSShreyas NC /* 2538541070ceSShreyas NC * Parse manifest private data for tokens. The private data block is 2539541070ceSShreyas NC * preceded by descriptors for type and size of data block. 2540541070ceSShreyas NC */ 2541541070ceSShreyas NC static int skl_tplg_get_manifest_data(struct snd_soc_tplg_manifest *manifest, 2542eee0e16fSJeeja KP struct device *dev, struct skl *skl) 2543541070ceSShreyas NC { 2544541070ceSShreyas NC struct snd_soc_tplg_vendor_array *array; 2545541070ceSShreyas NC int num_blocks, block_size = 0, block_type, off = 0; 2546541070ceSShreyas NC char *data; 2547541070ceSShreyas NC int ret; 2548541070ceSShreyas NC 2549541070ceSShreyas NC /* Read the NUM_DATA_BLOCKS descriptor */ 2550541070ceSShreyas NC array = (struct snd_soc_tplg_vendor_array *)manifest->priv.data; 2551541070ceSShreyas NC ret = skl_tplg_get_desc_blocks(dev, array); 2552541070ceSShreyas NC if (ret < 0) 2553541070ceSShreyas NC return ret; 2554541070ceSShreyas NC num_blocks = ret; 2555541070ceSShreyas NC 2556541070ceSShreyas NC off += array->size; 2557541070ceSShreyas NC array = (struct snd_soc_tplg_vendor_array *) 2558541070ceSShreyas NC (manifest->priv.data + off); 2559541070ceSShreyas NC 2560541070ceSShreyas NC /* Read the BLOCK_TYPE and BLOCK_SIZE descriptor */ 2561541070ceSShreyas NC while (num_blocks > 0) { 2562541070ceSShreyas NC ret = skl_tplg_get_desc_blocks(dev, array); 2563541070ceSShreyas NC 2564541070ceSShreyas NC if (ret < 0) 2565541070ceSShreyas NC return ret; 2566541070ceSShreyas NC block_type = ret; 2567541070ceSShreyas NC off += array->size; 2568541070ceSShreyas NC 2569541070ceSShreyas NC array = (struct snd_soc_tplg_vendor_array *) 2570541070ceSShreyas NC (manifest->priv.data + off); 2571541070ceSShreyas NC 2572541070ceSShreyas NC ret = skl_tplg_get_desc_blocks(dev, array); 2573541070ceSShreyas NC 2574541070ceSShreyas NC if (ret < 0) 2575541070ceSShreyas NC return ret; 2576541070ceSShreyas NC block_size = ret; 2577541070ceSShreyas NC off += array->size; 2578541070ceSShreyas NC 2579541070ceSShreyas NC array = (struct snd_soc_tplg_vendor_array *) 2580541070ceSShreyas NC (manifest->priv.data + off); 2581541070ceSShreyas NC 2582541070ceSShreyas NC data = (manifest->priv.data + off); 2583541070ceSShreyas NC 2584541070ceSShreyas NC if (block_type == SKL_TYPE_TUPLE) { 2585eee0e16fSJeeja KP ret = skl_tplg_get_manifest_tkn(dev, data, skl, 2586541070ceSShreyas NC block_size); 2587541070ceSShreyas NC 2588541070ceSShreyas NC if (ret < 0) 2589541070ceSShreyas NC return ret; 2590541070ceSShreyas NC 2591541070ceSShreyas NC --num_blocks; 2592541070ceSShreyas NC } else { 2593541070ceSShreyas NC return -EINVAL; 2594541070ceSShreyas NC } 2595541070ceSShreyas NC } 2596541070ceSShreyas NC 2597541070ceSShreyas NC return 0; 2598541070ceSShreyas NC } 2599541070ceSShreyas NC 260015ecaba9SKranthi G static int skl_manifest_load(struct snd_soc_component *cmpnt, 260115ecaba9SKranthi G struct snd_soc_tplg_manifest *manifest) 260215ecaba9SKranthi G { 260315ecaba9SKranthi G struct hdac_ext_bus *ebus = snd_soc_component_get_drvdata(cmpnt); 260415ecaba9SKranthi G struct hdac_bus *bus = ebus_to_hbus(ebus); 260515ecaba9SKranthi G struct skl *skl = ebus_to_skl(ebus); 260615ecaba9SKranthi G 2607c15ad605SVinod Koul /* proceed only if we have private data defined */ 2608c15ad605SVinod Koul if (manifest->priv.size == 0) 2609c15ad605SVinod Koul return 0; 2610c15ad605SVinod Koul 2611eee0e16fSJeeja KP skl_tplg_get_manifest_data(manifest, bus->dev, skl); 2612541070ceSShreyas NC 2613eee0e16fSJeeja KP if (skl->skl_sst->lib_count > SKL_MAX_LIB) { 261415ecaba9SKranthi G dev_err(bus->dev, "Exceeding max Library count. Got:%d\n", 2615eee0e16fSJeeja KP skl->skl_sst->lib_count); 2616eee0e16fSJeeja KP return -EINVAL; 261715ecaba9SKranthi G } 261815ecaba9SKranthi G 2619eee0e16fSJeeja KP return 0; 262015ecaba9SKranthi G } 262115ecaba9SKranthi G 26223af36706SVinod Koul static struct snd_soc_tplg_ops skl_tplg_ops = { 26233af36706SVinod Koul .widget_load = skl_tplg_widget_load, 2624140adfbaSJeeja KP .control_load = skl_tplg_control_load, 2625140adfbaSJeeja KP .bytes_ext_ops = skl_tlv_ops, 2626140adfbaSJeeja KP .bytes_ext_ops_count = ARRAY_SIZE(skl_tlv_ops), 262715ecaba9SKranthi G .manifest = skl_manifest_load, 26283af36706SVinod Koul }; 26293af36706SVinod Koul 2630287af4f9SJeeja KP /* 2631287af4f9SJeeja KP * A pipe can have multiple modules, each of them will be a DAPM widget as 2632287af4f9SJeeja KP * well. While managing a pipeline we need to get the list of all the 2633287af4f9SJeeja KP * widgets in a pipelines, so this helper - skl_tplg_create_pipe_widget_list() 2634287af4f9SJeeja KP * helps to get the SKL type widgets in that pipeline 2635287af4f9SJeeja KP */ 2636287af4f9SJeeja KP static int skl_tplg_create_pipe_widget_list(struct snd_soc_platform *platform) 2637287af4f9SJeeja KP { 2638287af4f9SJeeja KP struct snd_soc_dapm_widget *w; 2639287af4f9SJeeja KP struct skl_module_cfg *mcfg = NULL; 2640287af4f9SJeeja KP struct skl_pipe_module *p_module = NULL; 2641287af4f9SJeeja KP struct skl_pipe *pipe; 2642287af4f9SJeeja KP 2643287af4f9SJeeja KP list_for_each_entry(w, &platform->component.card->widgets, list) { 2644287af4f9SJeeja KP if (is_skl_dsp_widget_type(w) && w->priv != NULL) { 2645287af4f9SJeeja KP mcfg = w->priv; 2646287af4f9SJeeja KP pipe = mcfg->pipe; 2647287af4f9SJeeja KP 2648287af4f9SJeeja KP p_module = devm_kzalloc(platform->dev, 2649287af4f9SJeeja KP sizeof(*p_module), GFP_KERNEL); 2650287af4f9SJeeja KP if (!p_module) 2651287af4f9SJeeja KP return -ENOMEM; 2652287af4f9SJeeja KP 2653287af4f9SJeeja KP p_module->w = w; 2654287af4f9SJeeja KP list_add_tail(&p_module->node, &pipe->w_list); 2655287af4f9SJeeja KP } 2656287af4f9SJeeja KP } 2657287af4f9SJeeja KP 2658287af4f9SJeeja KP return 0; 2659287af4f9SJeeja KP } 2660287af4f9SJeeja KP 2661f0aa94faSJeeja KP static void skl_tplg_set_pipe_type(struct skl *skl, struct skl_pipe *pipe) 2662f0aa94faSJeeja KP { 2663f0aa94faSJeeja KP struct skl_pipe_module *w_module; 2664f0aa94faSJeeja KP struct snd_soc_dapm_widget *w; 2665f0aa94faSJeeja KP struct skl_module_cfg *mconfig; 2666f0aa94faSJeeja KP bool host_found = false, link_found = false; 2667f0aa94faSJeeja KP 2668f0aa94faSJeeja KP list_for_each_entry(w_module, &pipe->w_list, node) { 2669f0aa94faSJeeja KP w = w_module->w; 2670f0aa94faSJeeja KP mconfig = w->priv; 2671f0aa94faSJeeja KP 2672f0aa94faSJeeja KP if (mconfig->dev_type == SKL_DEVICE_HDAHOST) 2673f0aa94faSJeeja KP host_found = true; 2674f0aa94faSJeeja KP else if (mconfig->dev_type != SKL_DEVICE_NONE) 2675f0aa94faSJeeja KP link_found = true; 2676f0aa94faSJeeja KP } 2677f0aa94faSJeeja KP 2678f0aa94faSJeeja KP if (host_found && link_found) 2679f0aa94faSJeeja KP pipe->passthru = true; 2680f0aa94faSJeeja KP else 2681f0aa94faSJeeja KP pipe->passthru = false; 2682f0aa94faSJeeja KP } 2683f0aa94faSJeeja KP 26843af36706SVinod Koul /* This will be read from topology manifest, currently defined here */ 26853af36706SVinod Koul #define SKL_MAX_MCPS 30000000 26863af36706SVinod Koul #define SKL_FW_MAX_MEM 1000000 26873af36706SVinod Koul 26883af36706SVinod Koul /* 26893af36706SVinod Koul * SKL topology init routine 26903af36706SVinod Koul */ 26913af36706SVinod Koul int skl_tplg_init(struct snd_soc_platform *platform, struct hdac_ext_bus *ebus) 26923af36706SVinod Koul { 26933af36706SVinod Koul int ret; 26943af36706SVinod Koul const struct firmware *fw; 26953af36706SVinod Koul struct hdac_bus *bus = ebus_to_hbus(ebus); 26963af36706SVinod Koul struct skl *skl = ebus_to_skl(ebus); 2697f0aa94faSJeeja KP struct skl_pipeline *ppl; 26983af36706SVinod Koul 26994b235c43SVinod Koul ret = request_firmware(&fw, skl->tplg_name, bus->dev); 27003af36706SVinod Koul if (ret < 0) { 2701b663a8c5SJeeja KP dev_err(bus->dev, "tplg fw %s load failed with %d\n", 27024b235c43SVinod Koul skl->tplg_name, ret); 27034b235c43SVinod Koul ret = request_firmware(&fw, "dfw_sst.bin", bus->dev); 27044b235c43SVinod Koul if (ret < 0) { 27054b235c43SVinod Koul dev_err(bus->dev, "Fallback tplg fw %s load failed with %d\n", 27063af36706SVinod Koul "dfw_sst.bin", ret); 27073af36706SVinod Koul return ret; 27083af36706SVinod Koul } 27094b235c43SVinod Koul } 27103af36706SVinod Koul 27113af36706SVinod Koul /* 27123af36706SVinod Koul * The complete tplg for SKL is loaded as index 0, we don't use 27133af36706SVinod Koul * any other index 27143af36706SVinod Koul */ 2715b663a8c5SJeeja KP ret = snd_soc_tplg_component_load(&platform->component, 2716b663a8c5SJeeja KP &skl_tplg_ops, fw, 0); 27173af36706SVinod Koul if (ret < 0) { 27183af36706SVinod Koul dev_err(bus->dev, "tplg component load failed%d\n", ret); 2719c14a82c7SSudip Mukherjee release_firmware(fw); 27203af36706SVinod Koul return -EINVAL; 27213af36706SVinod Koul } 27223af36706SVinod Koul 27233af36706SVinod Koul skl->resource.max_mcps = SKL_MAX_MCPS; 27243af36706SVinod Koul skl->resource.max_mem = SKL_FW_MAX_MEM; 27253af36706SVinod Koul 2726d8018361SVinod Koul skl->tplg = fw; 2727287af4f9SJeeja KP ret = skl_tplg_create_pipe_widget_list(platform); 2728287af4f9SJeeja KP if (ret < 0) 2729287af4f9SJeeja KP return ret; 2730d8018361SVinod Koul 2731f0aa94faSJeeja KP list_for_each_entry(ppl, &skl->ppl_list, node) 2732f0aa94faSJeeja KP skl_tplg_set_pipe_type(skl, ppl->pipe); 27333af36706SVinod Koul 27343af36706SVinod Koul return 0; 2735e4e2d2f4SJeeja KP } 2736