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 397a1b749bSDharageswari R static const int mic_mono_list[] = { 407a1b749bSDharageswari R 0, 1, 2, 3, 417a1b749bSDharageswari R }; 427a1b749bSDharageswari R static const int mic_stereo_list[][SKL_CH_STEREO] = { 437a1b749bSDharageswari R {0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}, 447a1b749bSDharageswari R }; 457a1b749bSDharageswari R static const int mic_trio_list[][SKL_CH_TRIO] = { 467a1b749bSDharageswari R {0, 1, 2}, {0, 1, 3}, {0, 2, 3}, {1, 2, 3}, 477a1b749bSDharageswari R }; 487a1b749bSDharageswari R static const int mic_quatro_list[][SKL_CH_QUATRO] = { 497a1b749bSDharageswari R {0, 1, 2, 3}, 507a1b749bSDharageswari R }; 517a1b749bSDharageswari R 52a83e3b4cSVinod Koul void skl_tplg_d0i3_get(struct skl *skl, enum d0i3_capability caps) 53a83e3b4cSVinod Koul { 54a83e3b4cSVinod Koul struct skl_d0i3_data *d0i3 = &skl->skl_sst->d0i3; 55a83e3b4cSVinod Koul 56a83e3b4cSVinod Koul switch (caps) { 57a83e3b4cSVinod Koul case SKL_D0I3_NONE: 58a83e3b4cSVinod Koul d0i3->non_d0i3++; 59a83e3b4cSVinod Koul break; 60a83e3b4cSVinod Koul 61a83e3b4cSVinod Koul case SKL_D0I3_STREAMING: 62a83e3b4cSVinod Koul d0i3->streaming++; 63a83e3b4cSVinod Koul break; 64a83e3b4cSVinod Koul 65a83e3b4cSVinod Koul case SKL_D0I3_NON_STREAMING: 66a83e3b4cSVinod Koul d0i3->non_streaming++; 67a83e3b4cSVinod Koul break; 68a83e3b4cSVinod Koul } 69a83e3b4cSVinod Koul } 70a83e3b4cSVinod Koul 71a83e3b4cSVinod Koul void skl_tplg_d0i3_put(struct skl *skl, enum d0i3_capability caps) 72a83e3b4cSVinod Koul { 73a83e3b4cSVinod Koul struct skl_d0i3_data *d0i3 = &skl->skl_sst->d0i3; 74a83e3b4cSVinod Koul 75a83e3b4cSVinod Koul switch (caps) { 76a83e3b4cSVinod Koul case SKL_D0I3_NONE: 77a83e3b4cSVinod Koul d0i3->non_d0i3--; 78a83e3b4cSVinod Koul break; 79a83e3b4cSVinod Koul 80a83e3b4cSVinod Koul case SKL_D0I3_STREAMING: 81a83e3b4cSVinod Koul d0i3->streaming--; 82a83e3b4cSVinod Koul break; 83a83e3b4cSVinod Koul 84a83e3b4cSVinod Koul case SKL_D0I3_NON_STREAMING: 85a83e3b4cSVinod Koul d0i3->non_streaming--; 86a83e3b4cSVinod Koul break; 87a83e3b4cSVinod Koul } 88a83e3b4cSVinod Koul } 89a83e3b4cSVinod Koul 90e4e2d2f4SJeeja KP /* 91e4e2d2f4SJeeja KP * SKL DSP driver modelling uses only few DAPM widgets so for rest we will 92e4e2d2f4SJeeja KP * ignore. This helpers checks if the SKL driver handles this widget type 93e4e2d2f4SJeeja KP */ 94e4e2d2f4SJeeja KP static int is_skl_dsp_widget_type(struct snd_soc_dapm_widget *w) 95e4e2d2f4SJeeja KP { 96e4e2d2f4SJeeja KP switch (w->id) { 97e4e2d2f4SJeeja KP case snd_soc_dapm_dai_link: 98e4e2d2f4SJeeja KP case snd_soc_dapm_dai_in: 99e4e2d2f4SJeeja KP case snd_soc_dapm_aif_in: 100e4e2d2f4SJeeja KP case snd_soc_dapm_aif_out: 101e4e2d2f4SJeeja KP case snd_soc_dapm_dai_out: 102e4e2d2f4SJeeja KP case snd_soc_dapm_switch: 103e4e2d2f4SJeeja KP return false; 104e4e2d2f4SJeeja KP default: 105e4e2d2f4SJeeja KP return true; 106e4e2d2f4SJeeja KP } 107e4e2d2f4SJeeja KP } 108e4e2d2f4SJeeja KP 109e4e2d2f4SJeeja KP /* 110e4e2d2f4SJeeja KP * Each pipelines needs memory to be allocated. Check if we have free memory 1119ba8ffefSDharageswari.R * from available pool. 112e4e2d2f4SJeeja KP */ 1139ba8ffefSDharageswari.R static bool skl_is_pipe_mem_avail(struct skl *skl, 114e4e2d2f4SJeeja KP struct skl_module_cfg *mconfig) 115e4e2d2f4SJeeja KP { 116e4e2d2f4SJeeja KP struct skl_sst *ctx = skl->skl_sst; 117e4e2d2f4SJeeja KP 118e4e2d2f4SJeeja KP if (skl->resource.mem + mconfig->pipe->memory_pages > 119e4e2d2f4SJeeja KP skl->resource.max_mem) { 120e4e2d2f4SJeeja KP dev_err(ctx->dev, 121e4e2d2f4SJeeja KP "%s: module_id %d instance %d\n", __func__, 122e4e2d2f4SJeeja KP mconfig->id.module_id, 123e4e2d2f4SJeeja KP mconfig->id.instance_id); 124e4e2d2f4SJeeja KP dev_err(ctx->dev, 125e4e2d2f4SJeeja KP "exceeds ppl memory available %d mem %d\n", 126e4e2d2f4SJeeja KP skl->resource.max_mem, skl->resource.mem); 127e4e2d2f4SJeeja KP return false; 1289ba8ffefSDharageswari.R } else { 1299ba8ffefSDharageswari.R return true; 1309ba8ffefSDharageswari.R } 131e4e2d2f4SJeeja KP } 132e4e2d2f4SJeeja KP 1339ba8ffefSDharageswari.R /* 1349ba8ffefSDharageswari.R * Add the mem to the mem pool. This is freed when pipe is deleted. 1359ba8ffefSDharageswari.R * Note: DSP does actual memory management we only keep track for complete 1369ba8ffefSDharageswari.R * pool 1379ba8ffefSDharageswari.R */ 1389ba8ffefSDharageswari.R static void skl_tplg_alloc_pipe_mem(struct skl *skl, 1399ba8ffefSDharageswari.R struct skl_module_cfg *mconfig) 1409ba8ffefSDharageswari.R { 141e4e2d2f4SJeeja KP skl->resource.mem += mconfig->pipe->memory_pages; 142e4e2d2f4SJeeja KP } 143e4e2d2f4SJeeja KP 144e4e2d2f4SJeeja KP /* 145e4e2d2f4SJeeja KP * Pipeline needs needs DSP CPU resources for computation, this is 146e4e2d2f4SJeeja KP * quantified in MCPS (Million Clocks Per Second) required for module/pipe 147e4e2d2f4SJeeja KP * 148e4e2d2f4SJeeja KP * Each pipelines needs mcps to be allocated. Check if we have mcps for this 1499ba8ffefSDharageswari.R * pipe. 150e4e2d2f4SJeeja KP */ 1519ba8ffefSDharageswari.R 1529ba8ffefSDharageswari.R static bool skl_is_pipe_mcps_avail(struct skl *skl, 153e4e2d2f4SJeeja KP struct skl_module_cfg *mconfig) 154e4e2d2f4SJeeja KP { 155e4e2d2f4SJeeja KP struct skl_sst *ctx = skl->skl_sst; 156e4e2d2f4SJeeja KP 157e4e2d2f4SJeeja KP if (skl->resource.mcps + mconfig->mcps > skl->resource.max_mcps) { 158e4e2d2f4SJeeja KP dev_err(ctx->dev, 159e4e2d2f4SJeeja KP "%s: module_id %d instance %d\n", __func__, 160e4e2d2f4SJeeja KP mconfig->id.module_id, mconfig->id.instance_id); 161e4e2d2f4SJeeja KP dev_err(ctx->dev, 1627ca42f5aSGuneshwor Singh "exceeds ppl mcps available %d > mem %d\n", 163e4e2d2f4SJeeja KP skl->resource.max_mcps, skl->resource.mcps); 164e4e2d2f4SJeeja KP return false; 1659ba8ffefSDharageswari.R } else { 1669ba8ffefSDharageswari.R return true; 1679ba8ffefSDharageswari.R } 168e4e2d2f4SJeeja KP } 169e4e2d2f4SJeeja KP 1709ba8ffefSDharageswari.R static void skl_tplg_alloc_pipe_mcps(struct skl *skl, 1719ba8ffefSDharageswari.R struct skl_module_cfg *mconfig) 1729ba8ffefSDharageswari.R { 173e4e2d2f4SJeeja KP skl->resource.mcps += mconfig->mcps; 174e4e2d2f4SJeeja KP } 175e4e2d2f4SJeeja KP 176e4e2d2f4SJeeja KP /* 177e4e2d2f4SJeeja KP * Free the mcps when tearing down 178e4e2d2f4SJeeja KP */ 179e4e2d2f4SJeeja KP static void 180e4e2d2f4SJeeja KP skl_tplg_free_pipe_mcps(struct skl *skl, struct skl_module_cfg *mconfig) 181e4e2d2f4SJeeja KP { 182e4e2d2f4SJeeja KP skl->resource.mcps -= mconfig->mcps; 183e4e2d2f4SJeeja KP } 184e4e2d2f4SJeeja KP 185e4e2d2f4SJeeja KP /* 186e4e2d2f4SJeeja KP * Free the memory when tearing down 187e4e2d2f4SJeeja KP */ 188e4e2d2f4SJeeja KP static void 189e4e2d2f4SJeeja KP skl_tplg_free_pipe_mem(struct skl *skl, struct skl_module_cfg *mconfig) 190e4e2d2f4SJeeja KP { 191e4e2d2f4SJeeja KP skl->resource.mem -= mconfig->pipe->memory_pages; 192e4e2d2f4SJeeja KP } 193e4e2d2f4SJeeja KP 194f7590d4fSJeeja KP 195f7590d4fSJeeja KP static void skl_dump_mconfig(struct skl_sst *ctx, 196f7590d4fSJeeja KP struct skl_module_cfg *mcfg) 197f7590d4fSJeeja KP { 198f7590d4fSJeeja KP dev_dbg(ctx->dev, "Dumping config\n"); 199f7590d4fSJeeja KP dev_dbg(ctx->dev, "Input Format:\n"); 2004cd9899fSHardik T Shah dev_dbg(ctx->dev, "channels = %d\n", mcfg->in_fmt[0].channels); 2014cd9899fSHardik T Shah dev_dbg(ctx->dev, "s_freq = %d\n", mcfg->in_fmt[0].s_freq); 2024cd9899fSHardik T Shah dev_dbg(ctx->dev, "ch_cfg = %d\n", mcfg->in_fmt[0].ch_cfg); 2034cd9899fSHardik T Shah dev_dbg(ctx->dev, "valid bit depth = %d\n", mcfg->in_fmt[0].valid_bit_depth); 204f7590d4fSJeeja KP dev_dbg(ctx->dev, "Output Format:\n"); 2054cd9899fSHardik T Shah dev_dbg(ctx->dev, "channels = %d\n", mcfg->out_fmt[0].channels); 2064cd9899fSHardik T Shah dev_dbg(ctx->dev, "s_freq = %d\n", mcfg->out_fmt[0].s_freq); 2074cd9899fSHardik T Shah dev_dbg(ctx->dev, "valid bit depth = %d\n", mcfg->out_fmt[0].valid_bit_depth); 2084cd9899fSHardik T Shah dev_dbg(ctx->dev, "ch_cfg = %d\n", mcfg->out_fmt[0].ch_cfg); 209f7590d4fSJeeja KP } 210f7590d4fSJeeja KP 211ea5a137dSSubhransu S. Prusty static void skl_tplg_update_chmap(struct skl_module_fmt *fmt, int chs) 212ea5a137dSSubhransu S. Prusty { 213ea5a137dSSubhransu S. Prusty int slot_map = 0xFFFFFFFF; 214ea5a137dSSubhransu S. Prusty int start_slot = 0; 215ea5a137dSSubhransu S. Prusty int i; 216ea5a137dSSubhransu S. Prusty 217ea5a137dSSubhransu S. Prusty for (i = 0; i < chs; i++) { 218ea5a137dSSubhransu S. Prusty /* 219ea5a137dSSubhransu S. Prusty * For 2 channels with starting slot as 0, slot map will 220ea5a137dSSubhransu S. Prusty * look like 0xFFFFFF10. 221ea5a137dSSubhransu S. Prusty */ 222ea5a137dSSubhransu S. Prusty slot_map &= (~(0xF << (4 * i)) | (start_slot << (4 * i))); 223ea5a137dSSubhransu S. Prusty start_slot++; 224ea5a137dSSubhransu S. Prusty } 225ea5a137dSSubhransu S. Prusty fmt->ch_map = slot_map; 226ea5a137dSSubhransu S. Prusty } 227ea5a137dSSubhransu S. Prusty 228f7590d4fSJeeja KP static void skl_tplg_update_params(struct skl_module_fmt *fmt, 229f7590d4fSJeeja KP struct skl_pipe_params *params, int fixup) 230f7590d4fSJeeja KP { 231f7590d4fSJeeja KP if (fixup & SKL_RATE_FIXUP_MASK) 232f7590d4fSJeeja KP fmt->s_freq = params->s_freq; 233ea5a137dSSubhransu S. Prusty if (fixup & SKL_CH_FIXUP_MASK) { 234f7590d4fSJeeja KP fmt->channels = params->ch; 235ea5a137dSSubhransu S. Prusty skl_tplg_update_chmap(fmt, fmt->channels); 236ea5a137dSSubhransu S. Prusty } 23798256f83SJeeja KP if (fixup & SKL_FMT_FIXUP_MASK) { 23898256f83SJeeja KP fmt->valid_bit_depth = skl_get_bit_depth(params->s_fmt); 23998256f83SJeeja KP 24098256f83SJeeja KP /* 24198256f83SJeeja KP * 16 bit is 16 bit container whereas 24 bit is in 32 bit 24298256f83SJeeja KP * container so update bit depth accordingly 24398256f83SJeeja KP */ 24498256f83SJeeja KP switch (fmt->valid_bit_depth) { 24598256f83SJeeja KP case SKL_DEPTH_16BIT: 24698256f83SJeeja KP fmt->bit_depth = fmt->valid_bit_depth; 24798256f83SJeeja KP break; 24898256f83SJeeja KP 24998256f83SJeeja KP default: 25098256f83SJeeja KP fmt->bit_depth = SKL_DEPTH_32BIT; 25198256f83SJeeja KP break; 25298256f83SJeeja KP } 25398256f83SJeeja KP } 25498256f83SJeeja KP 255f7590d4fSJeeja KP } 256f7590d4fSJeeja KP 257f7590d4fSJeeja KP /* 258f7590d4fSJeeja KP * A pipeline may have modules which impact the pcm parameters, like SRC, 259f7590d4fSJeeja KP * channel converter, format converter. 260f7590d4fSJeeja KP * We need to calculate the output params by applying the 'fixup' 261f7590d4fSJeeja KP * Topology will tell driver which type of fixup is to be applied by 262f7590d4fSJeeja KP * supplying the fixup mask, so based on that we calculate the output 263f7590d4fSJeeja KP * 264f7590d4fSJeeja KP * Now In FE the pcm hw_params is source/target format. Same is applicable 265f7590d4fSJeeja KP * for BE with its hw_params invoked. 266f7590d4fSJeeja KP * here based on FE, BE pipeline and direction we calculate the input and 267f7590d4fSJeeja KP * outfix and then apply that for a module 268f7590d4fSJeeja KP */ 269f7590d4fSJeeja KP static void skl_tplg_update_params_fixup(struct skl_module_cfg *m_cfg, 270f7590d4fSJeeja KP struct skl_pipe_params *params, bool is_fe) 271f7590d4fSJeeja KP { 272f7590d4fSJeeja KP int in_fixup, out_fixup; 273f7590d4fSJeeja KP struct skl_module_fmt *in_fmt, *out_fmt; 274f7590d4fSJeeja KP 2754cd9899fSHardik T Shah /* Fixups will be applied to pin 0 only */ 2764cd9899fSHardik T Shah in_fmt = &m_cfg->in_fmt[0]; 2774cd9899fSHardik T Shah out_fmt = &m_cfg->out_fmt[0]; 278f7590d4fSJeeja KP 279f7590d4fSJeeja KP if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) { 280f7590d4fSJeeja KP if (is_fe) { 281f7590d4fSJeeja KP in_fixup = m_cfg->params_fixup; 282f7590d4fSJeeja KP out_fixup = (~m_cfg->converter) & 283f7590d4fSJeeja KP m_cfg->params_fixup; 284f7590d4fSJeeja KP } else { 285f7590d4fSJeeja KP out_fixup = m_cfg->params_fixup; 286f7590d4fSJeeja KP in_fixup = (~m_cfg->converter) & 287f7590d4fSJeeja KP m_cfg->params_fixup; 288f7590d4fSJeeja KP } 289f7590d4fSJeeja KP } else { 290f7590d4fSJeeja KP if (is_fe) { 291f7590d4fSJeeja KP out_fixup = m_cfg->params_fixup; 292f7590d4fSJeeja KP in_fixup = (~m_cfg->converter) & 293f7590d4fSJeeja KP m_cfg->params_fixup; 294f7590d4fSJeeja KP } else { 295f7590d4fSJeeja KP in_fixup = m_cfg->params_fixup; 296f7590d4fSJeeja KP out_fixup = (~m_cfg->converter) & 297f7590d4fSJeeja KP m_cfg->params_fixup; 298f7590d4fSJeeja KP } 299f7590d4fSJeeja KP } 300f7590d4fSJeeja KP 301f7590d4fSJeeja KP skl_tplg_update_params(in_fmt, params, in_fixup); 302f7590d4fSJeeja KP skl_tplg_update_params(out_fmt, params, out_fixup); 303f7590d4fSJeeja KP } 304f7590d4fSJeeja KP 305f7590d4fSJeeja KP /* 306f7590d4fSJeeja KP * A module needs input and output buffers, which are dependent upon pcm 307f7590d4fSJeeja KP * params, so once we have calculate params, we need buffer calculation as 308f7590d4fSJeeja KP * well. 309f7590d4fSJeeja KP */ 310f7590d4fSJeeja KP static void skl_tplg_update_buffer_size(struct skl_sst *ctx, 311f7590d4fSJeeja KP struct skl_module_cfg *mcfg) 312f7590d4fSJeeja KP { 313f7590d4fSJeeja KP int multiplier = 1; 3144cd9899fSHardik T Shah struct skl_module_fmt *in_fmt, *out_fmt; 3154cd9899fSHardik T Shah 3164cd9899fSHardik T Shah /* Since fixups is applied to pin 0 only, ibs, obs needs 3174cd9899fSHardik T Shah * change for pin 0 only 3184cd9899fSHardik T Shah */ 3194cd9899fSHardik T Shah in_fmt = &mcfg->in_fmt[0]; 3204cd9899fSHardik T Shah out_fmt = &mcfg->out_fmt[0]; 321f7590d4fSJeeja KP 322f7590d4fSJeeja KP if (mcfg->m_type == SKL_MODULE_TYPE_SRCINT) 323f7590d4fSJeeja KP multiplier = 5; 324f0c8e1d9SSubhransu S. Prusty 3258e15e762STakashi Sakamoto mcfg->ibs = DIV_ROUND_UP(in_fmt->s_freq, 1000) * 326998d6fb5STakashi Sakamoto in_fmt->channels * (in_fmt->bit_depth >> 3) * 327f7590d4fSJeeja KP multiplier; 328f7590d4fSJeeja KP 329998d6fb5STakashi Sakamoto mcfg->obs = DIV_ROUND_UP(out_fmt->s_freq, 1000) * 330998d6fb5STakashi Sakamoto out_fmt->channels * (out_fmt->bit_depth >> 3) * 331f7590d4fSJeeja KP multiplier; 332f7590d4fSJeeja KP } 333f7590d4fSJeeja KP 334db2f586bSSenthilnathan Veppur static u8 skl_tplg_be_dev_type(int dev_type) 335db2f586bSSenthilnathan Veppur { 336db2f586bSSenthilnathan Veppur int ret; 337db2f586bSSenthilnathan Veppur 338db2f586bSSenthilnathan Veppur switch (dev_type) { 339db2f586bSSenthilnathan Veppur case SKL_DEVICE_BT: 340db2f586bSSenthilnathan Veppur ret = NHLT_DEVICE_BT; 341db2f586bSSenthilnathan Veppur break; 342db2f586bSSenthilnathan Veppur 343db2f586bSSenthilnathan Veppur case SKL_DEVICE_DMIC: 344db2f586bSSenthilnathan Veppur ret = NHLT_DEVICE_DMIC; 345db2f586bSSenthilnathan Veppur break; 346db2f586bSSenthilnathan Veppur 347db2f586bSSenthilnathan Veppur case SKL_DEVICE_I2S: 348db2f586bSSenthilnathan Veppur ret = NHLT_DEVICE_I2S; 349db2f586bSSenthilnathan Veppur break; 350db2f586bSSenthilnathan Veppur 351db2f586bSSenthilnathan Veppur default: 352db2f586bSSenthilnathan Veppur ret = NHLT_DEVICE_INVALID; 353db2f586bSSenthilnathan Veppur break; 354db2f586bSSenthilnathan Veppur } 355db2f586bSSenthilnathan Veppur 356db2f586bSSenthilnathan Veppur return ret; 357db2f586bSSenthilnathan Veppur } 358db2f586bSSenthilnathan Veppur 3592d1419a3SJeeja KP static int skl_tplg_update_be_blob(struct snd_soc_dapm_widget *w, 3602d1419a3SJeeja KP struct skl_sst *ctx) 3612d1419a3SJeeja KP { 3622d1419a3SJeeja KP struct skl_module_cfg *m_cfg = w->priv; 3632d1419a3SJeeja KP int link_type, dir; 3642d1419a3SJeeja KP u32 ch, s_freq, s_fmt; 3652d1419a3SJeeja KP struct nhlt_specific_cfg *cfg; 3662d1419a3SJeeja KP struct skl *skl = get_skl_ctx(ctx->dev); 367db2f586bSSenthilnathan Veppur u8 dev_type = skl_tplg_be_dev_type(m_cfg->dev_type); 3682d1419a3SJeeja KP 3692d1419a3SJeeja KP /* check if we already have blob */ 3702d1419a3SJeeja KP if (m_cfg->formats_config.caps_size > 0) 3712d1419a3SJeeja KP return 0; 3722d1419a3SJeeja KP 373c7c6c736SJeeja KP dev_dbg(ctx->dev, "Applying default cfg blob\n"); 3742d1419a3SJeeja KP switch (m_cfg->dev_type) { 3752d1419a3SJeeja KP case SKL_DEVICE_DMIC: 3762d1419a3SJeeja KP link_type = NHLT_LINK_DMIC; 377c7c6c736SJeeja KP dir = SNDRV_PCM_STREAM_CAPTURE; 3782d1419a3SJeeja KP s_freq = m_cfg->in_fmt[0].s_freq; 3792d1419a3SJeeja KP s_fmt = m_cfg->in_fmt[0].bit_depth; 3802d1419a3SJeeja KP ch = m_cfg->in_fmt[0].channels; 3812d1419a3SJeeja KP break; 3822d1419a3SJeeja KP 3832d1419a3SJeeja KP case SKL_DEVICE_I2S: 3842d1419a3SJeeja KP link_type = NHLT_LINK_SSP; 3852d1419a3SJeeja KP if (m_cfg->hw_conn_type == SKL_CONN_SOURCE) { 386c7c6c736SJeeja KP dir = SNDRV_PCM_STREAM_PLAYBACK; 3872d1419a3SJeeja KP s_freq = m_cfg->out_fmt[0].s_freq; 3882d1419a3SJeeja KP s_fmt = m_cfg->out_fmt[0].bit_depth; 3892d1419a3SJeeja KP ch = m_cfg->out_fmt[0].channels; 390c7c6c736SJeeja KP } else { 391c7c6c736SJeeja KP dir = SNDRV_PCM_STREAM_CAPTURE; 392c7c6c736SJeeja KP s_freq = m_cfg->in_fmt[0].s_freq; 393c7c6c736SJeeja KP s_fmt = m_cfg->in_fmt[0].bit_depth; 394c7c6c736SJeeja KP ch = m_cfg->in_fmt[0].channels; 3952d1419a3SJeeja KP } 3962d1419a3SJeeja KP break; 3972d1419a3SJeeja KP 3982d1419a3SJeeja KP default: 3992d1419a3SJeeja KP return -EINVAL; 4002d1419a3SJeeja KP } 4012d1419a3SJeeja KP 4022d1419a3SJeeja KP /* update the blob based on virtual bus_id and default params */ 4032d1419a3SJeeja KP cfg = skl_get_ep_blob(skl, m_cfg->vbus_id, link_type, 404db2f586bSSenthilnathan Veppur s_fmt, ch, s_freq, dir, dev_type); 4052d1419a3SJeeja KP if (cfg) { 4062d1419a3SJeeja KP m_cfg->formats_config.caps_size = cfg->size; 4072d1419a3SJeeja KP m_cfg->formats_config.caps = (u32 *) &cfg->caps; 4082d1419a3SJeeja KP } else { 4092d1419a3SJeeja KP dev_err(ctx->dev, "Blob NULL for id %x type %d dirn %d\n", 4102d1419a3SJeeja KP m_cfg->vbus_id, link_type, dir); 4112d1419a3SJeeja KP dev_err(ctx->dev, "PCM: ch %d, freq %d, fmt %d\n", 4122d1419a3SJeeja KP ch, s_freq, s_fmt); 4132d1419a3SJeeja KP return -EIO; 4142d1419a3SJeeja KP } 4152d1419a3SJeeja KP 4162d1419a3SJeeja KP return 0; 4172d1419a3SJeeja KP } 4182d1419a3SJeeja KP 419f7590d4fSJeeja KP static void skl_tplg_update_module_params(struct snd_soc_dapm_widget *w, 420f7590d4fSJeeja KP struct skl_sst *ctx) 421f7590d4fSJeeja KP { 422f7590d4fSJeeja KP struct skl_module_cfg *m_cfg = w->priv; 423f7590d4fSJeeja KP struct skl_pipe_params *params = m_cfg->pipe->p_params; 424f7590d4fSJeeja KP int p_conn_type = m_cfg->pipe->conn_type; 425f7590d4fSJeeja KP bool is_fe; 426f7590d4fSJeeja KP 427f7590d4fSJeeja KP if (!m_cfg->params_fixup) 428f7590d4fSJeeja KP return; 429f7590d4fSJeeja KP 430f7590d4fSJeeja KP dev_dbg(ctx->dev, "Mconfig for widget=%s BEFORE updation\n", 431f7590d4fSJeeja KP w->name); 432f7590d4fSJeeja KP 433f7590d4fSJeeja KP skl_dump_mconfig(ctx, m_cfg); 434f7590d4fSJeeja KP 435f7590d4fSJeeja KP if (p_conn_type == SKL_PIPE_CONN_TYPE_FE) 436f7590d4fSJeeja KP is_fe = true; 437f7590d4fSJeeja KP else 438f7590d4fSJeeja KP is_fe = false; 439f7590d4fSJeeja KP 440f7590d4fSJeeja KP skl_tplg_update_params_fixup(m_cfg, params, is_fe); 441f7590d4fSJeeja KP skl_tplg_update_buffer_size(ctx, m_cfg); 442f7590d4fSJeeja KP 443f7590d4fSJeeja KP dev_dbg(ctx->dev, "Mconfig for widget=%s AFTER updation\n", 444f7590d4fSJeeja KP w->name); 445f7590d4fSJeeja KP 446f7590d4fSJeeja KP skl_dump_mconfig(ctx, m_cfg); 447f7590d4fSJeeja KP } 448f7590d4fSJeeja KP 449e4e2d2f4SJeeja KP /* 450abb74003SJeeja KP * some modules can have multiple params set from user control and 451abb74003SJeeja KP * need to be set after module is initialized. If set_param flag is 452abb74003SJeeja KP * set module params will be done after module is initialised. 453abb74003SJeeja KP */ 454abb74003SJeeja KP static int skl_tplg_set_module_params(struct snd_soc_dapm_widget *w, 455abb74003SJeeja KP struct skl_sst *ctx) 456abb74003SJeeja KP { 457abb74003SJeeja KP int i, ret; 458abb74003SJeeja KP struct skl_module_cfg *mconfig = w->priv; 459abb74003SJeeja KP const struct snd_kcontrol_new *k; 460abb74003SJeeja KP struct soc_bytes_ext *sb; 461abb74003SJeeja KP struct skl_algo_data *bc; 462abb74003SJeeja KP struct skl_specific_cfg *sp_cfg; 463abb74003SJeeja KP 464abb74003SJeeja KP if (mconfig->formats_config.caps_size > 0 && 4654ced1827SJeeja KP mconfig->formats_config.set_params == SKL_PARAM_SET) { 466abb74003SJeeja KP sp_cfg = &mconfig->formats_config; 467abb74003SJeeja KP ret = skl_set_module_params(ctx, sp_cfg->caps, 468abb74003SJeeja KP sp_cfg->caps_size, 469abb74003SJeeja KP sp_cfg->param_id, mconfig); 470abb74003SJeeja KP if (ret < 0) 471abb74003SJeeja KP return ret; 472abb74003SJeeja KP } 473abb74003SJeeja KP 474abb74003SJeeja KP for (i = 0; i < w->num_kcontrols; i++) { 475abb74003SJeeja KP k = &w->kcontrol_news[i]; 476abb74003SJeeja KP if (k->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { 477abb74003SJeeja KP sb = (void *) k->private_value; 478abb74003SJeeja KP bc = (struct skl_algo_data *)sb->dobj.private; 479abb74003SJeeja KP 4804ced1827SJeeja KP if (bc->set_params == SKL_PARAM_SET) { 481abb74003SJeeja KP ret = skl_set_module_params(ctx, 4820d682104SDharageswari R (u32 *)bc->params, bc->size, 483abb74003SJeeja KP bc->param_id, mconfig); 484abb74003SJeeja KP if (ret < 0) 485abb74003SJeeja KP return ret; 486abb74003SJeeja KP } 487abb74003SJeeja KP } 488abb74003SJeeja KP } 489abb74003SJeeja KP 490abb74003SJeeja KP return 0; 491abb74003SJeeja KP } 492abb74003SJeeja KP 493abb74003SJeeja KP /* 494abb74003SJeeja KP * some module param can set from user control and this is required as 495abb74003SJeeja KP * when module is initailzed. if module param is required in init it is 496abb74003SJeeja KP * identifed by set_param flag. if set_param flag is not set, then this 497abb74003SJeeja KP * parameter needs to set as part of module init. 498abb74003SJeeja KP */ 499abb74003SJeeja KP static int skl_tplg_set_module_init_data(struct snd_soc_dapm_widget *w) 500abb74003SJeeja KP { 501abb74003SJeeja KP const struct snd_kcontrol_new *k; 502abb74003SJeeja KP struct soc_bytes_ext *sb; 503abb74003SJeeja KP struct skl_algo_data *bc; 504abb74003SJeeja KP struct skl_module_cfg *mconfig = w->priv; 505abb74003SJeeja KP int i; 506abb74003SJeeja KP 507abb74003SJeeja KP for (i = 0; i < w->num_kcontrols; i++) { 508abb74003SJeeja KP k = &w->kcontrol_news[i]; 509abb74003SJeeja KP if (k->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { 510abb74003SJeeja KP sb = (struct soc_bytes_ext *)k->private_value; 511abb74003SJeeja KP bc = (struct skl_algo_data *)sb->dobj.private; 512abb74003SJeeja KP 5134ced1827SJeeja KP if (bc->set_params != SKL_PARAM_INIT) 514abb74003SJeeja KP continue; 515abb74003SJeeja KP 516d1a6fe41STakashi Sakamoto mconfig->formats_config.caps = (u32 *)bc->params; 5170d682104SDharageswari R mconfig->formats_config.caps_size = bc->size; 518abb74003SJeeja KP 519abb74003SJeeja KP break; 520abb74003SJeeja KP } 521abb74003SJeeja KP } 522abb74003SJeeja KP 523abb74003SJeeja KP return 0; 524abb74003SJeeja KP } 525abb74003SJeeja KP 526bb704a73SJeeja KP static int skl_tplg_module_prepare(struct skl_sst *ctx, struct skl_pipe *pipe, 527bb704a73SJeeja KP struct snd_soc_dapm_widget *w, struct skl_module_cfg *mcfg) 528bb704a73SJeeja KP { 529bb704a73SJeeja KP switch (mcfg->dev_type) { 530bb704a73SJeeja KP case SKL_DEVICE_HDAHOST: 531bb704a73SJeeja KP return skl_pcm_host_dma_prepare(ctx->dev, pipe->p_params); 532bb704a73SJeeja KP 533bb704a73SJeeja KP case SKL_DEVICE_HDALINK: 534bb704a73SJeeja KP return skl_pcm_link_dma_prepare(ctx->dev, pipe->p_params); 535bb704a73SJeeja KP } 536bb704a73SJeeja KP 537bb704a73SJeeja KP return 0; 538bb704a73SJeeja KP } 539bb704a73SJeeja KP 540abb74003SJeeja KP /* 541e4e2d2f4SJeeja KP * Inside a pipe instance, we can have various modules. These modules need 542e4e2d2f4SJeeja KP * to instantiated in DSP by invoking INIT_MODULE IPC, which is achieved by 543e4e2d2f4SJeeja KP * skl_init_module() routine, so invoke that for all modules in a pipeline 544e4e2d2f4SJeeja KP */ 545e4e2d2f4SJeeja KP static int 546e4e2d2f4SJeeja KP skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe) 547e4e2d2f4SJeeja KP { 548e4e2d2f4SJeeja KP struct skl_pipe_module *w_module; 549e4e2d2f4SJeeja KP struct snd_soc_dapm_widget *w; 550e4e2d2f4SJeeja KP struct skl_module_cfg *mconfig; 551e4e2d2f4SJeeja KP struct skl_sst *ctx = skl->skl_sst; 552e4e2d2f4SJeeja KP int ret = 0; 553e4e2d2f4SJeeja KP 554e4e2d2f4SJeeja KP list_for_each_entry(w_module, &pipe->w_list, node) { 555b26199eaSJeeja KP uuid_le *uuid_mod; 556e4e2d2f4SJeeja KP w = w_module->w; 557e4e2d2f4SJeeja KP mconfig = w->priv; 558e4e2d2f4SJeeja KP 559b7c50555SVinod Koul /* check if module ids are populated */ 560b7c50555SVinod Koul if (mconfig->id.module_id < 0) { 561b7c50555SVinod Koul dev_err(skl->skl_sst->dev, 562a657ae7eSVinod Koul "module %pUL id not populated\n", 563a657ae7eSVinod Koul (uuid_le *)mconfig->guid); 564a657ae7eSVinod Koul return -EIO; 565b7c50555SVinod Koul } 566b7c50555SVinod Koul 567e4e2d2f4SJeeja KP /* check resource available */ 5689ba8ffefSDharageswari.R if (!skl_is_pipe_mcps_avail(skl, mconfig)) 569e4e2d2f4SJeeja KP return -ENOMEM; 570e4e2d2f4SJeeja KP 5716c5768b3SDharageswari R if (mconfig->is_loadable && ctx->dsp->fw_ops.load_mod) { 5726c5768b3SDharageswari R ret = ctx->dsp->fw_ops.load_mod(ctx->dsp, 5736c5768b3SDharageswari R mconfig->id.module_id, mconfig->guid); 5746c5768b3SDharageswari R if (ret < 0) 5756c5768b3SDharageswari R return ret; 576d643678bSJeeja KP 577d643678bSJeeja KP mconfig->m_state = SKL_MODULE_LOADED; 5786c5768b3SDharageswari R } 5796c5768b3SDharageswari R 580bb704a73SJeeja KP /* prepare the DMA if the module is gateway cpr */ 581bb704a73SJeeja KP ret = skl_tplg_module_prepare(ctx, pipe, w, mconfig); 582bb704a73SJeeja KP if (ret < 0) 583bb704a73SJeeja KP return ret; 584bb704a73SJeeja KP 5852d1419a3SJeeja KP /* update blob if blob is null for be with default value */ 5862d1419a3SJeeja KP skl_tplg_update_be_blob(w, ctx); 5872d1419a3SJeeja KP 588f7590d4fSJeeja KP /* 589f7590d4fSJeeja KP * apply fix/conversion to module params based on 590f7590d4fSJeeja KP * FE/BE params 591f7590d4fSJeeja KP */ 592f7590d4fSJeeja KP skl_tplg_update_module_params(w, ctx); 593b26199eaSJeeja KP uuid_mod = (uuid_le *)mconfig->guid; 594b26199eaSJeeja KP mconfig->id.pvt_id = skl_get_pvt_id(ctx, uuid_mod, 595b26199eaSJeeja KP mconfig->id.instance_id); 596ef2a352cSDharageswari R if (mconfig->id.pvt_id < 0) 597ef2a352cSDharageswari R return ret; 598abb74003SJeeja KP skl_tplg_set_module_init_data(w); 5994147a6e5SPardha Saradhi K 6004147a6e5SPardha Saradhi K ret = skl_dsp_get_core(ctx->dsp, mconfig->core_id); 6014147a6e5SPardha Saradhi K if (ret < 0) { 6024147a6e5SPardha Saradhi K dev_err(ctx->dev, "Failed to wake up core %d ret=%d\n", 6034147a6e5SPardha Saradhi K mconfig->core_id, ret); 6044147a6e5SPardha Saradhi K return ret; 6054147a6e5SPardha Saradhi K } 6064147a6e5SPardha Saradhi K 6079939a9c3SJeeja KP ret = skl_init_module(ctx, mconfig); 608ef2a352cSDharageswari R if (ret < 0) { 609b26199eaSJeeja KP skl_put_pvt_id(ctx, uuid_mod, &mconfig->id.pvt_id); 6104147a6e5SPardha Saradhi K goto err; 611ef2a352cSDharageswari R } 612260eb73aSDharageswari R skl_tplg_alloc_pipe_mcps(skl, mconfig); 613abb74003SJeeja KP ret = skl_tplg_set_module_params(w, ctx); 614e4e2d2f4SJeeja KP if (ret < 0) 6154147a6e5SPardha Saradhi K goto err; 616e4e2d2f4SJeeja KP } 617e4e2d2f4SJeeja KP 618e4e2d2f4SJeeja KP return 0; 6194147a6e5SPardha Saradhi K err: 6204147a6e5SPardha Saradhi K skl_dsp_put_core(ctx->dsp, mconfig->core_id); 6214147a6e5SPardha Saradhi K return ret; 622e4e2d2f4SJeeja KP } 623d93f8e55SVinod Koul 6246c5768b3SDharageswari R static int skl_tplg_unload_pipe_modules(struct skl_sst *ctx, 6256c5768b3SDharageswari R struct skl_pipe *pipe) 6266c5768b3SDharageswari R { 6274147a6e5SPardha Saradhi K int ret = 0; 6286c5768b3SDharageswari R struct skl_pipe_module *w_module = NULL; 6296c5768b3SDharageswari R struct skl_module_cfg *mconfig = NULL; 6306c5768b3SDharageswari R 6316c5768b3SDharageswari R list_for_each_entry(w_module, &pipe->w_list, node) { 632b26199eaSJeeja KP uuid_le *uuid_mod; 6336c5768b3SDharageswari R mconfig = w_module->w->priv; 634b26199eaSJeeja KP uuid_mod = (uuid_le *)mconfig->guid; 6356c5768b3SDharageswari R 636d643678bSJeeja KP if (mconfig->is_loadable && ctx->dsp->fw_ops.unload_mod && 637b0fab9c6SDharageswari R mconfig->m_state > SKL_MODULE_UNINIT) { 638b0fab9c6SDharageswari R ret = ctx->dsp->fw_ops.unload_mod(ctx->dsp, 6396c5768b3SDharageswari R mconfig->id.module_id); 640b0fab9c6SDharageswari R if (ret < 0) 641b0fab9c6SDharageswari R return -EIO; 642b0fab9c6SDharageswari R } 643b26199eaSJeeja KP skl_put_pvt_id(ctx, uuid_mod, &mconfig->id.pvt_id); 6444147a6e5SPardha Saradhi K 6454147a6e5SPardha Saradhi K ret = skl_dsp_put_core(ctx->dsp, mconfig->core_id); 6464147a6e5SPardha Saradhi K if (ret < 0) { 6474147a6e5SPardha Saradhi K /* don't return; continue with other modules */ 6484147a6e5SPardha Saradhi K dev_err(ctx->dev, "Failed to sleep core %d ret=%d\n", 6494147a6e5SPardha Saradhi K mconfig->core_id, ret); 6504147a6e5SPardha Saradhi K } 6516c5768b3SDharageswari R } 6526c5768b3SDharageswari R 6536c5768b3SDharageswari R /* no modules to unload in this path, so return */ 6544147a6e5SPardha Saradhi K return ret; 6556c5768b3SDharageswari R } 6566c5768b3SDharageswari R 657d93f8e55SVinod Koul /* 658d93f8e55SVinod Koul * Mixer module represents a pipeline. So in the Pre-PMU event of mixer we 659d93f8e55SVinod Koul * need create the pipeline. So we do following: 660d93f8e55SVinod Koul * - check the resources 661d93f8e55SVinod Koul * - Create the pipeline 662d93f8e55SVinod Koul * - Initialize the modules in pipeline 663d93f8e55SVinod Koul * - finally bind all modules together 664d93f8e55SVinod Koul */ 665d93f8e55SVinod Koul static int skl_tplg_mixer_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w, 666d93f8e55SVinod Koul struct skl *skl) 667d93f8e55SVinod Koul { 668d93f8e55SVinod Koul int ret; 669d93f8e55SVinod Koul struct skl_module_cfg *mconfig = w->priv; 670d93f8e55SVinod Koul struct skl_pipe_module *w_module; 671d93f8e55SVinod Koul struct skl_pipe *s_pipe = mconfig->pipe; 672b8c722ddSJeeja KP struct skl_module_cfg *src_module = NULL, *dst_module, *module; 673d93f8e55SVinod Koul struct skl_sst *ctx = skl->skl_sst; 674b8c722ddSJeeja KP struct skl_module_deferred_bind *modules; 675d93f8e55SVinod Koul 676d93f8e55SVinod Koul /* check resource available */ 6779ba8ffefSDharageswari.R if (!skl_is_pipe_mcps_avail(skl, mconfig)) 678d93f8e55SVinod Koul return -EBUSY; 679d93f8e55SVinod Koul 6809ba8ffefSDharageswari.R if (!skl_is_pipe_mem_avail(skl, mconfig)) 681d93f8e55SVinod Koul return -ENOMEM; 682d93f8e55SVinod Koul 683d93f8e55SVinod Koul /* 684d93f8e55SVinod Koul * Create a list of modules for pipe. 685d93f8e55SVinod Koul * This list contains modules from source to sink 686d93f8e55SVinod Koul */ 687d93f8e55SVinod Koul ret = skl_create_pipeline(ctx, mconfig->pipe); 688d93f8e55SVinod Koul if (ret < 0) 689d93f8e55SVinod Koul return ret; 690d93f8e55SVinod Koul 691260eb73aSDharageswari R skl_tplg_alloc_pipe_mem(skl, mconfig); 692260eb73aSDharageswari R skl_tplg_alloc_pipe_mcps(skl, mconfig); 693d93f8e55SVinod Koul 694d93f8e55SVinod Koul /* Init all pipe modules from source to sink */ 695d93f8e55SVinod Koul ret = skl_tplg_init_pipe_modules(skl, s_pipe); 696d93f8e55SVinod Koul if (ret < 0) 697d93f8e55SVinod Koul return ret; 698d93f8e55SVinod Koul 699d93f8e55SVinod Koul /* Bind modules from source to sink */ 700d93f8e55SVinod Koul list_for_each_entry(w_module, &s_pipe->w_list, node) { 701d93f8e55SVinod Koul dst_module = w_module->w->priv; 702d93f8e55SVinod Koul 703d93f8e55SVinod Koul if (src_module == NULL) { 704d93f8e55SVinod Koul src_module = dst_module; 705d93f8e55SVinod Koul continue; 706d93f8e55SVinod Koul } 707d93f8e55SVinod Koul 708d93f8e55SVinod Koul ret = skl_bind_modules(ctx, src_module, dst_module); 709d93f8e55SVinod Koul if (ret < 0) 710d93f8e55SVinod Koul return ret; 711d93f8e55SVinod Koul 712d93f8e55SVinod Koul src_module = dst_module; 713d93f8e55SVinod Koul } 714d93f8e55SVinod Koul 715b8c722ddSJeeja KP /* 716b8c722ddSJeeja KP * When the destination module is initialized, check for these modules 717b8c722ddSJeeja KP * in deferred bind list. If found, bind them. 718b8c722ddSJeeja KP */ 719b8c722ddSJeeja KP list_for_each_entry(w_module, &s_pipe->w_list, node) { 720b8c722ddSJeeja KP if (list_empty(&skl->bind_list)) 721b8c722ddSJeeja KP break; 722b8c722ddSJeeja KP 723b8c722ddSJeeja KP list_for_each_entry(modules, &skl->bind_list, node) { 724b8c722ddSJeeja KP module = w_module->w->priv; 725b8c722ddSJeeja KP if (modules->dst == module) 726b8c722ddSJeeja KP skl_bind_modules(ctx, modules->src, 727b8c722ddSJeeja KP modules->dst); 728b8c722ddSJeeja KP } 729b8c722ddSJeeja KP } 730b8c722ddSJeeja KP 731d93f8e55SVinod Koul return 0; 732d93f8e55SVinod Koul } 733d93f8e55SVinod Koul 734bf3e5ef5SDharageswari R static int skl_fill_sink_instance_id(struct skl_sst *ctx, u32 *params, 735bf3e5ef5SDharageswari R int size, struct skl_module_cfg *mcfg) 7365e8f0ee4SDharageswari R { 7375e8f0ee4SDharageswari R int i, pvt_id; 7385e8f0ee4SDharageswari R 739bf3e5ef5SDharageswari R if (mcfg->m_type == SKL_MODULE_TYPE_KPB) { 740bf3e5ef5SDharageswari R struct skl_kpb_params *kpb_params = 741bf3e5ef5SDharageswari R (struct skl_kpb_params *)params; 742bf3e5ef5SDharageswari R struct skl_mod_inst_map *inst = kpb_params->map; 7435e8f0ee4SDharageswari R 744bf3e5ef5SDharageswari R for (i = 0; i < kpb_params->num_modules; i++) { 745bf3e5ef5SDharageswari R pvt_id = skl_get_pvt_instance_id_map(ctx, inst->mod_id, 746bf3e5ef5SDharageswari R inst->inst_id); 7475e8f0ee4SDharageswari R if (pvt_id < 0) 7485e8f0ee4SDharageswari R return -EINVAL; 749bf3e5ef5SDharageswari R 7505e8f0ee4SDharageswari R inst->inst_id = pvt_id; 7515e8f0ee4SDharageswari R inst++; 7525e8f0ee4SDharageswari R } 7535e8f0ee4SDharageswari R } 7545e8f0ee4SDharageswari R 755bf3e5ef5SDharageswari R return 0; 756bf3e5ef5SDharageswari R } 757cc6a4044SJeeja KP /* 758cc6a4044SJeeja KP * Some modules require params to be set after the module is bound to 759cc6a4044SJeeja KP * all pins connected. 760cc6a4044SJeeja KP * 761cc6a4044SJeeja KP * The module provider initializes set_param flag for such modules and we 762cc6a4044SJeeja KP * send params after binding 763cc6a4044SJeeja KP */ 764cc6a4044SJeeja KP static int skl_tplg_set_module_bind_params(struct snd_soc_dapm_widget *w, 765cc6a4044SJeeja KP struct skl_module_cfg *mcfg, struct skl_sst *ctx) 766cc6a4044SJeeja KP { 767cc6a4044SJeeja KP int i, ret; 768cc6a4044SJeeja KP struct skl_module_cfg *mconfig = w->priv; 769cc6a4044SJeeja KP const struct snd_kcontrol_new *k; 770cc6a4044SJeeja KP struct soc_bytes_ext *sb; 771cc6a4044SJeeja KP struct skl_algo_data *bc; 772cc6a4044SJeeja KP struct skl_specific_cfg *sp_cfg; 773bf3e5ef5SDharageswari R u32 *params; 774cc6a4044SJeeja KP 775cc6a4044SJeeja KP /* 776cc6a4044SJeeja KP * check all out/in pins are in bind state. 777cc6a4044SJeeja KP * if so set the module param 778cc6a4044SJeeja KP */ 779cc6a4044SJeeja KP for (i = 0; i < mcfg->max_out_queue; i++) { 780cc6a4044SJeeja KP if (mcfg->m_out_pin[i].pin_state != SKL_PIN_BIND_DONE) 781cc6a4044SJeeja KP return 0; 782cc6a4044SJeeja KP } 783cc6a4044SJeeja KP 784cc6a4044SJeeja KP for (i = 0; i < mcfg->max_in_queue; i++) { 785cc6a4044SJeeja KP if (mcfg->m_in_pin[i].pin_state != SKL_PIN_BIND_DONE) 786cc6a4044SJeeja KP return 0; 787cc6a4044SJeeja KP } 788cc6a4044SJeeja KP 789cc6a4044SJeeja KP if (mconfig->formats_config.caps_size > 0 && 790cc6a4044SJeeja KP mconfig->formats_config.set_params == SKL_PARAM_BIND) { 791cc6a4044SJeeja KP sp_cfg = &mconfig->formats_config; 792cc6a4044SJeeja KP ret = skl_set_module_params(ctx, sp_cfg->caps, 793cc6a4044SJeeja KP sp_cfg->caps_size, 794cc6a4044SJeeja KP sp_cfg->param_id, mconfig); 795cc6a4044SJeeja KP if (ret < 0) 796cc6a4044SJeeja KP return ret; 797cc6a4044SJeeja KP } 798cc6a4044SJeeja KP 799cc6a4044SJeeja KP for (i = 0; i < w->num_kcontrols; i++) { 800cc6a4044SJeeja KP k = &w->kcontrol_news[i]; 801cc6a4044SJeeja KP if (k->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { 802cc6a4044SJeeja KP sb = (void *) k->private_value; 803cc6a4044SJeeja KP bc = (struct skl_algo_data *)sb->dobj.private; 804cc6a4044SJeeja KP 805cc6a4044SJeeja KP if (bc->set_params == SKL_PARAM_BIND) { 806bf3e5ef5SDharageswari R params = kzalloc(bc->max, GFP_KERNEL); 807bf3e5ef5SDharageswari R if (!params) 808bf3e5ef5SDharageswari R return -ENOMEM; 809bf3e5ef5SDharageswari R 810bf3e5ef5SDharageswari R memcpy(params, bc->params, bc->max); 811bf3e5ef5SDharageswari R skl_fill_sink_instance_id(ctx, params, bc->max, 812bf3e5ef5SDharageswari R mconfig); 813bf3e5ef5SDharageswari R 814bf3e5ef5SDharageswari R ret = skl_set_module_params(ctx, params, 815bf3e5ef5SDharageswari R bc->max, bc->param_id, mconfig); 816bf3e5ef5SDharageswari R kfree(params); 817bf3e5ef5SDharageswari R 818cc6a4044SJeeja KP if (ret < 0) 819cc6a4044SJeeja KP return ret; 820cc6a4044SJeeja KP } 821cc6a4044SJeeja KP } 822cc6a4044SJeeja KP } 823cc6a4044SJeeja KP 824cc6a4044SJeeja KP return 0; 825cc6a4044SJeeja KP } 826cc6a4044SJeeja KP 827b8c722ddSJeeja KP 828b8c722ddSJeeja KP static int skl_tplg_module_add_deferred_bind(struct skl *skl, 829b8c722ddSJeeja KP struct skl_module_cfg *src, struct skl_module_cfg *dst) 830b8c722ddSJeeja KP { 831b8c722ddSJeeja KP struct skl_module_deferred_bind *m_list, *modules; 832b8c722ddSJeeja KP int i; 833b8c722ddSJeeja KP 834b8c722ddSJeeja KP /* only supported for module with static pin connection */ 835b8c722ddSJeeja KP for (i = 0; i < dst->max_in_queue; i++) { 836b8c722ddSJeeja KP struct skl_module_pin *pin = &dst->m_in_pin[i]; 837b8c722ddSJeeja KP 838b8c722ddSJeeja KP if (pin->is_dynamic) 839b8c722ddSJeeja KP continue; 840b8c722ddSJeeja KP 841b8c722ddSJeeja KP if ((pin->id.module_id == src->id.module_id) && 842b8c722ddSJeeja KP (pin->id.instance_id == src->id.instance_id)) { 843b8c722ddSJeeja KP 844b8c722ddSJeeja KP if (!list_empty(&skl->bind_list)) { 845b8c722ddSJeeja KP list_for_each_entry(modules, &skl->bind_list, node) { 846b8c722ddSJeeja KP if (modules->src == src && modules->dst == dst) 847b8c722ddSJeeja KP return 0; 848b8c722ddSJeeja KP } 849b8c722ddSJeeja KP } 850b8c722ddSJeeja KP 851b8c722ddSJeeja KP m_list = kzalloc(sizeof(*m_list), GFP_KERNEL); 852b8c722ddSJeeja KP if (!m_list) 853b8c722ddSJeeja KP return -ENOMEM; 854b8c722ddSJeeja KP 855b8c722ddSJeeja KP m_list->src = src; 856b8c722ddSJeeja KP m_list->dst = dst; 857b8c722ddSJeeja KP 858b8c722ddSJeeja KP list_add(&m_list->node, &skl->bind_list); 859b8c722ddSJeeja KP } 860b8c722ddSJeeja KP } 861b8c722ddSJeeja KP 862b8c722ddSJeeja KP return 0; 863b8c722ddSJeeja KP } 864b8c722ddSJeeja KP 8658724ff17SJeeja KP static int skl_tplg_bind_sinks(struct snd_soc_dapm_widget *w, 8668724ff17SJeeja KP struct skl *skl, 8676bd4cf85SJeeja KP struct snd_soc_dapm_widget *src_w, 8688724ff17SJeeja KP struct skl_module_cfg *src_mconfig) 869d93f8e55SVinod Koul { 870d93f8e55SVinod Koul struct snd_soc_dapm_path *p; 8710ed95d76SJeeja KP struct snd_soc_dapm_widget *sink = NULL, *next_sink = NULL; 8728724ff17SJeeja KP struct skl_module_cfg *sink_mconfig; 873d93f8e55SVinod Koul struct skl_sst *ctx = skl->skl_sst; 8748724ff17SJeeja KP int ret; 875d93f8e55SVinod Koul 8768724ff17SJeeja KP snd_soc_dapm_widget_for_each_sink_path(w, p) { 877d93f8e55SVinod Koul if (!p->connect) 878d93f8e55SVinod Koul continue; 879d93f8e55SVinod Koul 880d93f8e55SVinod Koul dev_dbg(ctx->dev, "%s: src widget=%s\n", __func__, w->name); 881d93f8e55SVinod Koul dev_dbg(ctx->dev, "%s: sink widget=%s\n", __func__, p->sink->name); 882d93f8e55SVinod Koul 8830ed95d76SJeeja KP next_sink = p->sink; 8846bd4cf85SJeeja KP 8856bd4cf85SJeeja KP if (!is_skl_dsp_widget_type(p->sink)) 8866bd4cf85SJeeja KP return skl_tplg_bind_sinks(p->sink, skl, src_w, src_mconfig); 8876bd4cf85SJeeja KP 888d93f8e55SVinod Koul /* 889d93f8e55SVinod Koul * here we will check widgets in sink pipelines, so that 890d93f8e55SVinod Koul * can be any widgets type and we are only interested if 891d93f8e55SVinod Koul * they are ones used for SKL so check that first 892d93f8e55SVinod Koul */ 893d93f8e55SVinod Koul if ((p->sink->priv != NULL) && 894d93f8e55SVinod Koul is_skl_dsp_widget_type(p->sink)) { 895d93f8e55SVinod Koul 896d93f8e55SVinod Koul sink = p->sink; 897d93f8e55SVinod Koul sink_mconfig = sink->priv; 898d93f8e55SVinod Koul 899b8c722ddSJeeja KP /* 900b8c722ddSJeeja KP * Modules other than PGA leaf can be connected 901b8c722ddSJeeja KP * directly or via switch to a module in another 902b8c722ddSJeeja KP * pipeline. EX: reference path 903b8c722ddSJeeja KP * when the path is enabled, the dst module that needs 904b8c722ddSJeeja KP * to be bound may not be initialized. if the module is 905b8c722ddSJeeja KP * not initialized, add these modules in the deferred 906b8c722ddSJeeja KP * bind list and when the dst module is initialised, 907b8c722ddSJeeja KP * bind this module to the dst_module in deferred list. 908b8c722ddSJeeja KP */ 909b8c722ddSJeeja KP if (((src_mconfig->m_state == SKL_MODULE_INIT_DONE) 910b8c722ddSJeeja KP && (sink_mconfig->m_state == SKL_MODULE_UNINIT))) { 911b8c722ddSJeeja KP 912b8c722ddSJeeja KP ret = skl_tplg_module_add_deferred_bind(skl, 913b8c722ddSJeeja KP src_mconfig, sink_mconfig); 914b8c722ddSJeeja KP 915b8c722ddSJeeja KP if (ret < 0) 916b8c722ddSJeeja KP return ret; 917b8c722ddSJeeja KP 918b8c722ddSJeeja KP } 919b8c722ddSJeeja KP 920b8c722ddSJeeja KP 921cc6a4044SJeeja KP if (src_mconfig->m_state == SKL_MODULE_UNINIT || 922cc6a4044SJeeja KP sink_mconfig->m_state == SKL_MODULE_UNINIT) 923cc6a4044SJeeja KP continue; 924cc6a4044SJeeja KP 925d93f8e55SVinod Koul /* Bind source to sink, mixin is always source */ 926d93f8e55SVinod Koul ret = skl_bind_modules(ctx, src_mconfig, sink_mconfig); 927d93f8e55SVinod Koul if (ret) 928d93f8e55SVinod Koul return ret; 929d93f8e55SVinod Koul 930cc6a4044SJeeja KP /* set module params after bind */ 931cc6a4044SJeeja KP skl_tplg_set_module_bind_params(src_w, src_mconfig, ctx); 932cc6a4044SJeeja KP skl_tplg_set_module_bind_params(sink, sink_mconfig, ctx); 933cc6a4044SJeeja KP 934d93f8e55SVinod Koul /* Start sinks pipe first */ 935d93f8e55SVinod Koul if (sink_mconfig->pipe->state != SKL_PIPE_STARTED) { 936d1730c3dSJeeja KP if (sink_mconfig->pipe->conn_type != 937d1730c3dSJeeja KP SKL_PIPE_CONN_TYPE_FE) 938d1730c3dSJeeja KP ret = skl_run_pipe(ctx, 939d1730c3dSJeeja KP sink_mconfig->pipe); 940d93f8e55SVinod Koul if (ret) 941d93f8e55SVinod Koul return ret; 942d93f8e55SVinod Koul } 943d93f8e55SVinod Koul } 944d93f8e55SVinod Koul } 945d93f8e55SVinod Koul 94610a5439fSguneshwor.o.singh@intel.com if (!sink && next_sink) 9476bd4cf85SJeeja KP return skl_tplg_bind_sinks(next_sink, skl, src_w, src_mconfig); 9488724ff17SJeeja KP 9498724ff17SJeeja KP return 0; 9508724ff17SJeeja KP } 9518724ff17SJeeja KP 952d93f8e55SVinod Koul /* 953d93f8e55SVinod Koul * A PGA represents a module in a pipeline. So in the Pre-PMU event of PGA 954d93f8e55SVinod Koul * we need to do following: 955d93f8e55SVinod Koul * - Bind to sink pipeline 956d93f8e55SVinod Koul * Since the sink pipes can be running and we don't get mixer event on 957d93f8e55SVinod Koul * connect for already running mixer, we need to find the sink pipes 958d93f8e55SVinod Koul * here and bind to them. This way dynamic connect works. 959d93f8e55SVinod Koul * - Start sink pipeline, if not running 960d93f8e55SVinod Koul * - Then run current pipe 961d93f8e55SVinod Koul */ 962d93f8e55SVinod Koul static int skl_tplg_pga_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w, 963d93f8e55SVinod Koul struct skl *skl) 964d93f8e55SVinod Koul { 9658724ff17SJeeja KP struct skl_module_cfg *src_mconfig; 966d93f8e55SVinod Koul struct skl_sst *ctx = skl->skl_sst; 967d93f8e55SVinod Koul int ret = 0; 968d93f8e55SVinod Koul 9698724ff17SJeeja KP src_mconfig = w->priv; 970d93f8e55SVinod Koul 971d93f8e55SVinod Koul /* 972d93f8e55SVinod Koul * find which sink it is connected to, bind with the sink, 973d93f8e55SVinod Koul * if sink is not started, start sink pipe first, then start 974d93f8e55SVinod Koul * this pipe 975d93f8e55SVinod Koul */ 9766bd4cf85SJeeja KP ret = skl_tplg_bind_sinks(w, skl, w, src_mconfig); 9778724ff17SJeeja KP if (ret) 9788724ff17SJeeja KP return ret; 9798724ff17SJeeja KP 980d93f8e55SVinod Koul /* Start source pipe last after starting all sinks */ 981d1730c3dSJeeja KP if (src_mconfig->pipe->conn_type != SKL_PIPE_CONN_TYPE_FE) 982d1730c3dSJeeja KP return skl_run_pipe(ctx, src_mconfig->pipe); 983d93f8e55SVinod Koul 984d93f8e55SVinod Koul return 0; 985d93f8e55SVinod Koul } 986d93f8e55SVinod Koul 9878724ff17SJeeja KP static struct snd_soc_dapm_widget *skl_get_src_dsp_widget( 9888724ff17SJeeja KP struct snd_soc_dapm_widget *w, struct skl *skl) 9898724ff17SJeeja KP { 9908724ff17SJeeja KP struct snd_soc_dapm_path *p; 9918724ff17SJeeja KP struct snd_soc_dapm_widget *src_w = NULL; 9928724ff17SJeeja KP struct skl_sst *ctx = skl->skl_sst; 9938724ff17SJeeja KP 994d93f8e55SVinod Koul snd_soc_dapm_widget_for_each_source_path(w, p) { 9958724ff17SJeeja KP src_w = p->source; 996d93f8e55SVinod Koul if (!p->connect) 997d93f8e55SVinod Koul continue; 998d93f8e55SVinod Koul 9998724ff17SJeeja KP dev_dbg(ctx->dev, "sink widget=%s\n", w->name); 10008724ff17SJeeja KP dev_dbg(ctx->dev, "src widget=%s\n", p->source->name); 1001d93f8e55SVinod Koul 1002d93f8e55SVinod Koul /* 10038724ff17SJeeja KP * here we will check widgets in sink pipelines, so that can 10048724ff17SJeeja KP * be any widgets type and we are only interested if they are 10058724ff17SJeeja KP * ones used for SKL so check that first 1006d93f8e55SVinod Koul */ 10078724ff17SJeeja KP if ((p->source->priv != NULL) && 10088724ff17SJeeja KP is_skl_dsp_widget_type(p->source)) { 10098724ff17SJeeja KP return p->source; 1010d93f8e55SVinod Koul } 1011d93f8e55SVinod Koul } 1012d93f8e55SVinod Koul 10138724ff17SJeeja KP if (src_w != NULL) 10148724ff17SJeeja KP return skl_get_src_dsp_widget(src_w, skl); 1015d93f8e55SVinod Koul 10168724ff17SJeeja KP return NULL; 1017d93f8e55SVinod Koul } 1018d93f8e55SVinod Koul 1019d93f8e55SVinod Koul /* 1020d93f8e55SVinod Koul * in the Post-PMU event of mixer we need to do following: 1021d93f8e55SVinod Koul * - Check if this pipe is running 1022d93f8e55SVinod Koul * - if not, then 1023d93f8e55SVinod Koul * - bind this pipeline to its source pipeline 1024d93f8e55SVinod Koul * if source pipe is already running, this means it is a dynamic 1025d93f8e55SVinod Koul * connection and we need to bind only to that pipe 1026d93f8e55SVinod Koul * - start this pipeline 1027d93f8e55SVinod Koul */ 1028d93f8e55SVinod Koul static int skl_tplg_mixer_dapm_post_pmu_event(struct snd_soc_dapm_widget *w, 1029d93f8e55SVinod Koul struct skl *skl) 1030d93f8e55SVinod Koul { 1031d93f8e55SVinod Koul int ret = 0; 1032d93f8e55SVinod Koul struct snd_soc_dapm_widget *source, *sink; 1033d93f8e55SVinod Koul struct skl_module_cfg *src_mconfig, *sink_mconfig; 1034d93f8e55SVinod Koul struct skl_sst *ctx = skl->skl_sst; 1035d93f8e55SVinod Koul int src_pipe_started = 0; 1036d93f8e55SVinod Koul 1037d93f8e55SVinod Koul sink = w; 1038d93f8e55SVinod Koul sink_mconfig = sink->priv; 1039d93f8e55SVinod Koul 1040d93f8e55SVinod Koul /* 1041d93f8e55SVinod Koul * If source pipe is already started, that means source is driving 1042d93f8e55SVinod Koul * one more sink before this sink got connected, Since source is 1043d93f8e55SVinod Koul * started, bind this sink to source and start this pipe. 1044d93f8e55SVinod Koul */ 10458724ff17SJeeja KP source = skl_get_src_dsp_widget(w, skl); 10468724ff17SJeeja KP if (source != NULL) { 1047d93f8e55SVinod Koul src_mconfig = source->priv; 1048d93f8e55SVinod Koul sink_mconfig = sink->priv; 1049d93f8e55SVinod Koul src_pipe_started = 1; 1050d93f8e55SVinod Koul 1051d93f8e55SVinod Koul /* 10528724ff17SJeeja KP * check pipe state, then no need to bind or start the 10538724ff17SJeeja KP * pipe 1054d93f8e55SVinod Koul */ 1055d93f8e55SVinod Koul if (src_mconfig->pipe->state != SKL_PIPE_STARTED) 1056d93f8e55SVinod Koul src_pipe_started = 0; 1057d93f8e55SVinod Koul } 1058d93f8e55SVinod Koul 1059d93f8e55SVinod Koul if (src_pipe_started) { 1060d93f8e55SVinod Koul ret = skl_bind_modules(ctx, src_mconfig, sink_mconfig); 1061d93f8e55SVinod Koul if (ret) 1062d93f8e55SVinod Koul return ret; 1063d93f8e55SVinod Koul 1064cc6a4044SJeeja KP /* set module params after bind */ 1065cc6a4044SJeeja KP skl_tplg_set_module_bind_params(source, src_mconfig, ctx); 1066cc6a4044SJeeja KP skl_tplg_set_module_bind_params(sink, sink_mconfig, ctx); 1067cc6a4044SJeeja KP 1068d1730c3dSJeeja KP if (sink_mconfig->pipe->conn_type != SKL_PIPE_CONN_TYPE_FE) 1069d93f8e55SVinod Koul ret = skl_run_pipe(ctx, sink_mconfig->pipe); 1070d93f8e55SVinod Koul } 1071d93f8e55SVinod Koul 1072d93f8e55SVinod Koul return ret; 1073d93f8e55SVinod Koul } 1074d93f8e55SVinod Koul 1075d93f8e55SVinod Koul /* 1076d93f8e55SVinod Koul * in the Pre-PMD event of mixer we need to do following: 1077d93f8e55SVinod Koul * - Stop the pipe 1078d93f8e55SVinod Koul * - find the source connections and remove that from dapm_path_list 1079d93f8e55SVinod Koul * - unbind with source pipelines if still connected 1080d93f8e55SVinod Koul */ 1081d93f8e55SVinod Koul static int skl_tplg_mixer_dapm_pre_pmd_event(struct snd_soc_dapm_widget *w, 1082d93f8e55SVinod Koul struct skl *skl) 1083d93f8e55SVinod Koul { 1084d93f8e55SVinod Koul struct skl_module_cfg *src_mconfig, *sink_mconfig; 1085ce1b5551SJeeja KP int ret = 0, i; 1086d93f8e55SVinod Koul struct skl_sst *ctx = skl->skl_sst; 1087d93f8e55SVinod Koul 1088ce1b5551SJeeja KP sink_mconfig = w->priv; 1089d93f8e55SVinod Koul 1090d93f8e55SVinod Koul /* Stop the pipe */ 1091d93f8e55SVinod Koul ret = skl_stop_pipe(ctx, sink_mconfig->pipe); 1092d93f8e55SVinod Koul if (ret) 1093d93f8e55SVinod Koul return ret; 1094d93f8e55SVinod Koul 1095ce1b5551SJeeja KP for (i = 0; i < sink_mconfig->max_in_queue; i++) { 1096ce1b5551SJeeja KP if (sink_mconfig->m_in_pin[i].pin_state == SKL_PIN_BIND_DONE) { 1097ce1b5551SJeeja KP src_mconfig = sink_mconfig->m_in_pin[i].tgt_mcfg; 1098ce1b5551SJeeja KP if (!src_mconfig) 1099ce1b5551SJeeja KP continue; 1100d93f8e55SVinod Koul 1101ce1b5551SJeeja KP ret = skl_unbind_modules(ctx, 1102ce1b5551SJeeja KP src_mconfig, sink_mconfig); 1103ce1b5551SJeeja KP } 1104d93f8e55SVinod Koul } 1105d93f8e55SVinod Koul 1106d93f8e55SVinod Koul return ret; 1107d93f8e55SVinod Koul } 1108d93f8e55SVinod Koul 1109d93f8e55SVinod Koul /* 1110d93f8e55SVinod Koul * in the Post-PMD event of mixer we need to do following: 1111d93f8e55SVinod Koul * - Free the mcps used 1112d93f8e55SVinod Koul * - Free the mem used 1113d93f8e55SVinod Koul * - Unbind the modules within the pipeline 1114d93f8e55SVinod Koul * - Delete the pipeline (modules are not required to be explicitly 1115d93f8e55SVinod Koul * deleted, pipeline delete is enough here 1116d93f8e55SVinod Koul */ 1117d93f8e55SVinod Koul static int skl_tplg_mixer_dapm_post_pmd_event(struct snd_soc_dapm_widget *w, 1118d93f8e55SVinod Koul struct skl *skl) 1119d93f8e55SVinod Koul { 1120d93f8e55SVinod Koul struct skl_module_cfg *mconfig = w->priv; 1121d93f8e55SVinod Koul struct skl_pipe_module *w_module; 1122d93f8e55SVinod Koul struct skl_module_cfg *src_module = NULL, *dst_module; 1123d93f8e55SVinod Koul struct skl_sst *ctx = skl->skl_sst; 1124d93f8e55SVinod Koul struct skl_pipe *s_pipe = mconfig->pipe; 1125550b349aSDan Carpenter struct skl_module_deferred_bind *modules, *tmp; 1126d93f8e55SVinod Koul 1127260eb73aSDharageswari R if (s_pipe->state == SKL_PIPE_INVALID) 1128260eb73aSDharageswari R return -EINVAL; 1129260eb73aSDharageswari R 1130d93f8e55SVinod Koul skl_tplg_free_pipe_mcps(skl, mconfig); 113165976878SVinod Koul skl_tplg_free_pipe_mem(skl, mconfig); 1132d93f8e55SVinod Koul 1133d93f8e55SVinod Koul list_for_each_entry(w_module, &s_pipe->w_list, node) { 1134b8c722ddSJeeja KP if (list_empty(&skl->bind_list)) 1135b8c722ddSJeeja KP break; 1136b8c722ddSJeeja KP 1137b8c722ddSJeeja KP src_module = w_module->w->priv; 1138b8c722ddSJeeja KP 1139550b349aSDan Carpenter list_for_each_entry_safe(modules, tmp, &skl->bind_list, node) { 1140b8c722ddSJeeja KP /* 1141b8c722ddSJeeja KP * When the destination module is deleted, Unbind the 1142b8c722ddSJeeja KP * modules from deferred bind list. 1143b8c722ddSJeeja KP */ 1144b8c722ddSJeeja KP if (modules->dst == src_module) { 1145b8c722ddSJeeja KP skl_unbind_modules(ctx, modules->src, 1146b8c722ddSJeeja KP modules->dst); 1147b8c722ddSJeeja KP } 1148b8c722ddSJeeja KP 1149b8c722ddSJeeja KP /* 1150b8c722ddSJeeja KP * When the source module is deleted, remove this entry 1151b8c722ddSJeeja KP * from the deferred bind list. 1152b8c722ddSJeeja KP */ 1153b8c722ddSJeeja KP if (modules->src == src_module) { 1154b8c722ddSJeeja KP list_del(&modules->node); 1155b8c722ddSJeeja KP modules->src = NULL; 1156b8c722ddSJeeja KP modules->dst = NULL; 1157b8c722ddSJeeja KP kfree(modules); 1158b8c722ddSJeeja KP } 1159b8c722ddSJeeja KP } 1160b8c722ddSJeeja KP } 1161b8c722ddSJeeja KP 1162b8c722ddSJeeja KP list_for_each_entry(w_module, &s_pipe->w_list, node) { 1163d93f8e55SVinod Koul dst_module = w_module->w->priv; 1164d93f8e55SVinod Koul 1165260eb73aSDharageswari R if (mconfig->m_state >= SKL_MODULE_INIT_DONE) 11667ae3cb15SVinod Koul skl_tplg_free_pipe_mcps(skl, dst_module); 1167d93f8e55SVinod Koul if (src_module == NULL) { 1168d93f8e55SVinod Koul src_module = dst_module; 1169d93f8e55SVinod Koul continue; 1170d93f8e55SVinod Koul } 1171d93f8e55SVinod Koul 11727ca42f5aSGuneshwor Singh skl_unbind_modules(ctx, src_module, dst_module); 1173d93f8e55SVinod Koul src_module = dst_module; 1174d93f8e55SVinod Koul } 1175d93f8e55SVinod Koul 1176547cafa3SVinod Koul skl_delete_pipe(ctx, mconfig->pipe); 1177d93f8e55SVinod Koul 1178473a4d51SJeeja KP list_for_each_entry(w_module, &s_pipe->w_list, node) { 1179473a4d51SJeeja KP src_module = w_module->w->priv; 1180473a4d51SJeeja KP src_module->m_state = SKL_MODULE_UNINIT; 1181473a4d51SJeeja KP } 1182473a4d51SJeeja KP 11836c5768b3SDharageswari R return skl_tplg_unload_pipe_modules(ctx, s_pipe); 1184d93f8e55SVinod Koul } 1185d93f8e55SVinod Koul 1186d93f8e55SVinod Koul /* 1187d93f8e55SVinod Koul * in the Post-PMD event of PGA we need to do following: 1188d93f8e55SVinod Koul * - Free the mcps used 1189d93f8e55SVinod Koul * - Stop the pipeline 1190d93f8e55SVinod Koul * - In source pipe is connected, unbind with source pipelines 1191d93f8e55SVinod Koul */ 1192d93f8e55SVinod Koul static int skl_tplg_pga_dapm_post_pmd_event(struct snd_soc_dapm_widget *w, 1193d93f8e55SVinod Koul struct skl *skl) 1194d93f8e55SVinod Koul { 1195d93f8e55SVinod Koul struct skl_module_cfg *src_mconfig, *sink_mconfig; 1196ce1b5551SJeeja KP int ret = 0, i; 1197d93f8e55SVinod Koul struct skl_sst *ctx = skl->skl_sst; 1198d93f8e55SVinod Koul 1199ce1b5551SJeeja KP src_mconfig = w->priv; 1200d93f8e55SVinod Koul 1201d93f8e55SVinod Koul /* Stop the pipe since this is a mixin module */ 1202d93f8e55SVinod Koul ret = skl_stop_pipe(ctx, src_mconfig->pipe); 1203d93f8e55SVinod Koul if (ret) 1204d93f8e55SVinod Koul return ret; 1205d93f8e55SVinod Koul 1206ce1b5551SJeeja KP for (i = 0; i < src_mconfig->max_out_queue; i++) { 1207ce1b5551SJeeja KP if (src_mconfig->m_out_pin[i].pin_state == SKL_PIN_BIND_DONE) { 1208ce1b5551SJeeja KP sink_mconfig = src_mconfig->m_out_pin[i].tgt_mcfg; 1209ce1b5551SJeeja KP if (!sink_mconfig) 1210ce1b5551SJeeja KP continue; 1211d93f8e55SVinod Koul /* 1212ce1b5551SJeeja KP * This is a connecter and if path is found that means 1213d93f8e55SVinod Koul * unbind between source and sink has not happened yet 1214d93f8e55SVinod Koul */ 1215ce1b5551SJeeja KP ret = skl_unbind_modules(ctx, src_mconfig, 1216ce1b5551SJeeja KP sink_mconfig); 1217ce1b5551SJeeja KP } 1218d93f8e55SVinod Koul } 1219d93f8e55SVinod Koul 1220d93f8e55SVinod Koul return ret; 1221d93f8e55SVinod Koul } 1222d93f8e55SVinod Koul 1223d93f8e55SVinod Koul /* 1224d93f8e55SVinod Koul * In modelling, we assume there will be ONLY one mixer in a pipeline. If a 1225d93f8e55SVinod Koul * second one is required that is created as another pipe entity. 1226d93f8e55SVinod Koul * The mixer is responsible for pipe management and represent a pipeline 1227d93f8e55SVinod Koul * instance 1228d93f8e55SVinod Koul */ 1229d93f8e55SVinod Koul static int skl_tplg_mixer_event(struct snd_soc_dapm_widget *w, 1230d93f8e55SVinod Koul struct snd_kcontrol *k, int event) 1231d93f8e55SVinod Koul { 1232d93f8e55SVinod Koul struct snd_soc_dapm_context *dapm = w->dapm; 1233d93f8e55SVinod Koul struct skl *skl = get_skl_ctx(dapm->dev); 1234d93f8e55SVinod Koul 1235d93f8e55SVinod Koul switch (event) { 1236d93f8e55SVinod Koul case SND_SOC_DAPM_PRE_PMU: 1237d93f8e55SVinod Koul return skl_tplg_mixer_dapm_pre_pmu_event(w, skl); 1238d93f8e55SVinod Koul 1239d93f8e55SVinod Koul case SND_SOC_DAPM_POST_PMU: 1240d93f8e55SVinod Koul return skl_tplg_mixer_dapm_post_pmu_event(w, skl); 1241d93f8e55SVinod Koul 1242d93f8e55SVinod Koul case SND_SOC_DAPM_PRE_PMD: 1243d93f8e55SVinod Koul return skl_tplg_mixer_dapm_pre_pmd_event(w, skl); 1244d93f8e55SVinod Koul 1245d93f8e55SVinod Koul case SND_SOC_DAPM_POST_PMD: 1246d93f8e55SVinod Koul return skl_tplg_mixer_dapm_post_pmd_event(w, skl); 1247d93f8e55SVinod Koul } 1248d93f8e55SVinod Koul 1249d93f8e55SVinod Koul return 0; 1250d93f8e55SVinod Koul } 1251d93f8e55SVinod Koul 1252d93f8e55SVinod Koul /* 1253d93f8e55SVinod Koul * In modelling, we assumed rest of the modules in pipeline are PGA. But we 1254d93f8e55SVinod Koul * are interested in last PGA (leaf PGA) in a pipeline to disconnect with 1255d93f8e55SVinod Koul * the sink when it is running (two FE to one BE or one FE to two BE) 1256d93f8e55SVinod Koul * scenarios 1257d93f8e55SVinod Koul */ 1258d93f8e55SVinod Koul static int skl_tplg_pga_event(struct snd_soc_dapm_widget *w, 1259d93f8e55SVinod Koul struct snd_kcontrol *k, int event) 1260d93f8e55SVinod Koul 1261d93f8e55SVinod Koul { 1262d93f8e55SVinod Koul struct snd_soc_dapm_context *dapm = w->dapm; 1263d93f8e55SVinod Koul struct skl *skl = get_skl_ctx(dapm->dev); 1264d93f8e55SVinod Koul 1265d93f8e55SVinod Koul switch (event) { 1266d93f8e55SVinod Koul case SND_SOC_DAPM_PRE_PMU: 1267d93f8e55SVinod Koul return skl_tplg_pga_dapm_pre_pmu_event(w, skl); 1268d93f8e55SVinod Koul 1269d93f8e55SVinod Koul case SND_SOC_DAPM_POST_PMD: 1270d93f8e55SVinod Koul return skl_tplg_pga_dapm_post_pmd_event(w, skl); 1271d93f8e55SVinod Koul } 1272d93f8e55SVinod Koul 1273d93f8e55SVinod Koul return 0; 1274d93f8e55SVinod Koul } 1275cfb0a873SVinod Koul 1276140adfbaSJeeja KP static int skl_tplg_tlv_control_get(struct snd_kcontrol *kcontrol, 1277140adfbaSJeeja KP unsigned int __user *data, unsigned int size) 1278140adfbaSJeeja KP { 1279140adfbaSJeeja KP struct soc_bytes_ext *sb = 1280140adfbaSJeeja KP (struct soc_bytes_ext *)kcontrol->private_value; 1281140adfbaSJeeja KP struct skl_algo_data *bc = (struct skl_algo_data *)sb->dobj.private; 12827d9f2911SOmair M Abdullah struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol); 12837d9f2911SOmair M Abdullah struct skl_module_cfg *mconfig = w->priv; 12847d9f2911SOmair M Abdullah struct skl *skl = get_skl_ctx(w->dapm->dev); 12857d9f2911SOmair M Abdullah 12867d9f2911SOmair M Abdullah if (w->power) 12877d9f2911SOmair M Abdullah skl_get_module_params(skl->skl_sst, (u32 *)bc->params, 12880d682104SDharageswari R bc->size, bc->param_id, mconfig); 1289140adfbaSJeeja KP 129041556f68SVinod Koul /* decrement size for TLV header */ 129141556f68SVinod Koul size -= 2 * sizeof(u32); 129241556f68SVinod Koul 129341556f68SVinod Koul /* check size as we don't want to send kernel data */ 129441556f68SVinod Koul if (size > bc->max) 129541556f68SVinod Koul size = bc->max; 129641556f68SVinod Koul 1297140adfbaSJeeja KP if (bc->params) { 1298140adfbaSJeeja KP if (copy_to_user(data, &bc->param_id, sizeof(u32))) 1299140adfbaSJeeja KP return -EFAULT; 1300e8bc3c99SDan Carpenter if (copy_to_user(data + 1, &size, sizeof(u32))) 1301140adfbaSJeeja KP return -EFAULT; 1302e8bc3c99SDan Carpenter if (copy_to_user(data + 2, bc->params, size)) 1303140adfbaSJeeja KP return -EFAULT; 1304140adfbaSJeeja KP } 1305140adfbaSJeeja KP 1306140adfbaSJeeja KP return 0; 1307140adfbaSJeeja KP } 1308140adfbaSJeeja KP 1309140adfbaSJeeja KP #define SKL_PARAM_VENDOR_ID 0xff 1310140adfbaSJeeja KP 1311140adfbaSJeeja KP static int skl_tplg_tlv_control_set(struct snd_kcontrol *kcontrol, 1312140adfbaSJeeja KP const unsigned int __user *data, unsigned int size) 1313140adfbaSJeeja KP { 1314140adfbaSJeeja KP struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol); 1315140adfbaSJeeja KP struct skl_module_cfg *mconfig = w->priv; 1316140adfbaSJeeja KP struct soc_bytes_ext *sb = 1317140adfbaSJeeja KP (struct soc_bytes_ext *)kcontrol->private_value; 1318140adfbaSJeeja KP struct skl_algo_data *ac = (struct skl_algo_data *)sb->dobj.private; 1319140adfbaSJeeja KP struct skl *skl = get_skl_ctx(w->dapm->dev); 1320140adfbaSJeeja KP 1321140adfbaSJeeja KP if (ac->params) { 13220d682104SDharageswari R if (size > ac->max) 13230d682104SDharageswari R return -EINVAL; 13240d682104SDharageswari R 13250d682104SDharageswari R ac->size = size; 1326140adfbaSJeeja KP /* 1327140adfbaSJeeja KP * if the param_is is of type Vendor, firmware expects actual 1328140adfbaSJeeja KP * parameter id and size from the control. 1329140adfbaSJeeja KP */ 1330140adfbaSJeeja KP if (ac->param_id == SKL_PARAM_VENDOR_ID) { 1331140adfbaSJeeja KP if (copy_from_user(ac->params, data, size)) 1332140adfbaSJeeja KP return -EFAULT; 1333140adfbaSJeeja KP } else { 1334140adfbaSJeeja KP if (copy_from_user(ac->params, 133565b4bcb8SAlan data + 2, size)) 1336140adfbaSJeeja KP return -EFAULT; 1337140adfbaSJeeja KP } 1338140adfbaSJeeja KP 1339140adfbaSJeeja KP if (w->power) 1340140adfbaSJeeja KP return skl_set_module_params(skl->skl_sst, 13410d682104SDharageswari R (u32 *)ac->params, ac->size, 1342140adfbaSJeeja KP ac->param_id, mconfig); 1343140adfbaSJeeja KP } 1344140adfbaSJeeja KP 1345140adfbaSJeeja KP return 0; 1346140adfbaSJeeja KP } 1347140adfbaSJeeja KP 13487a1b749bSDharageswari R static int skl_tplg_mic_control_get(struct snd_kcontrol *kcontrol, 13497a1b749bSDharageswari R struct snd_ctl_elem_value *ucontrol) 13507a1b749bSDharageswari R { 13517a1b749bSDharageswari R struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol); 13527a1b749bSDharageswari R struct skl_module_cfg *mconfig = w->priv; 13537a1b749bSDharageswari R struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; 13547a1b749bSDharageswari R u32 ch_type = *((u32 *)ec->dobj.private); 13557a1b749bSDharageswari R 13567a1b749bSDharageswari R if (mconfig->dmic_ch_type == ch_type) 13577a1b749bSDharageswari R ucontrol->value.enumerated.item[0] = 13587a1b749bSDharageswari R mconfig->dmic_ch_combo_index; 13597a1b749bSDharageswari R else 13607a1b749bSDharageswari R ucontrol->value.enumerated.item[0] = 0; 13617a1b749bSDharageswari R 13627a1b749bSDharageswari R return 0; 13637a1b749bSDharageswari R } 13647a1b749bSDharageswari R 13657a1b749bSDharageswari R static int skl_fill_mic_sel_params(struct skl_module_cfg *mconfig, 13667a1b749bSDharageswari R struct skl_mic_sel_config *mic_cfg, struct device *dev) 13677a1b749bSDharageswari R { 13687a1b749bSDharageswari R struct skl_specific_cfg *sp_cfg = &mconfig->formats_config; 13697a1b749bSDharageswari R 13707a1b749bSDharageswari R sp_cfg->caps_size = sizeof(struct skl_mic_sel_config); 13717a1b749bSDharageswari R sp_cfg->set_params = SKL_PARAM_SET; 13727a1b749bSDharageswari R sp_cfg->param_id = 0x00; 13737a1b749bSDharageswari R if (!sp_cfg->caps) { 13747a1b749bSDharageswari R sp_cfg->caps = devm_kzalloc(dev, sp_cfg->caps_size, GFP_KERNEL); 13757a1b749bSDharageswari R if (!sp_cfg->caps) 13767a1b749bSDharageswari R return -ENOMEM; 13777a1b749bSDharageswari R } 13787a1b749bSDharageswari R 13797a1b749bSDharageswari R mic_cfg->mic_switch = SKL_MIC_SEL_SWITCH; 13807a1b749bSDharageswari R mic_cfg->flags = 0; 13817a1b749bSDharageswari R memcpy(sp_cfg->caps, mic_cfg, sp_cfg->caps_size); 13827a1b749bSDharageswari R 13837a1b749bSDharageswari R return 0; 13847a1b749bSDharageswari R } 13857a1b749bSDharageswari R 13867a1b749bSDharageswari R static int skl_tplg_mic_control_set(struct snd_kcontrol *kcontrol, 13877a1b749bSDharageswari R struct snd_ctl_elem_value *ucontrol) 13887a1b749bSDharageswari R { 13897a1b749bSDharageswari R struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol); 13907a1b749bSDharageswari R struct skl_module_cfg *mconfig = w->priv; 13917a1b749bSDharageswari R struct skl_mic_sel_config mic_cfg = {0}; 13927a1b749bSDharageswari R struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; 13937a1b749bSDharageswari R u32 ch_type = *((u32 *)ec->dobj.private); 13947a1b749bSDharageswari R const int *list; 13957a1b749bSDharageswari R u8 in_ch, out_ch, index; 13967a1b749bSDharageswari R 13977a1b749bSDharageswari R mconfig->dmic_ch_type = ch_type; 13987a1b749bSDharageswari R mconfig->dmic_ch_combo_index = ucontrol->value.enumerated.item[0]; 13997a1b749bSDharageswari R 14007a1b749bSDharageswari R /* enum control index 0 is INVALID, so no channels to be set */ 14017a1b749bSDharageswari R if (mconfig->dmic_ch_combo_index == 0) 14027a1b749bSDharageswari R return 0; 14037a1b749bSDharageswari R 14047a1b749bSDharageswari R /* No valid channel selection map for index 0, so offset by 1 */ 14057a1b749bSDharageswari R index = mconfig->dmic_ch_combo_index - 1; 14067a1b749bSDharageswari R 14077a1b749bSDharageswari R switch (ch_type) { 14087a1b749bSDharageswari R case SKL_CH_MONO: 14097a1b749bSDharageswari R if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_mono_list)) 14107a1b749bSDharageswari R return -EINVAL; 14117a1b749bSDharageswari R 14127a1b749bSDharageswari R list = &mic_mono_list[index]; 14137a1b749bSDharageswari R break; 14147a1b749bSDharageswari R 14157a1b749bSDharageswari R case SKL_CH_STEREO: 14167a1b749bSDharageswari R if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_stereo_list)) 14177a1b749bSDharageswari R return -EINVAL; 14187a1b749bSDharageswari R 14197a1b749bSDharageswari R list = mic_stereo_list[index]; 14207a1b749bSDharageswari R break; 14217a1b749bSDharageswari R 14227a1b749bSDharageswari R case SKL_CH_TRIO: 14237a1b749bSDharageswari R if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_trio_list)) 14247a1b749bSDharageswari R return -EINVAL; 14257a1b749bSDharageswari R 14267a1b749bSDharageswari R list = mic_trio_list[index]; 14277a1b749bSDharageswari R break; 14287a1b749bSDharageswari R 14297a1b749bSDharageswari R case SKL_CH_QUATRO: 14307a1b749bSDharageswari R if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_quatro_list)) 14317a1b749bSDharageswari R return -EINVAL; 14327a1b749bSDharageswari R 14337a1b749bSDharageswari R list = mic_quatro_list[index]; 14347a1b749bSDharageswari R break; 14357a1b749bSDharageswari R 14367a1b749bSDharageswari R default: 14377a1b749bSDharageswari R dev_err(w->dapm->dev, 14387a1b749bSDharageswari R "Invalid channel %d for mic_select module\n", 14397a1b749bSDharageswari R ch_type); 14407a1b749bSDharageswari R return -EINVAL; 14417a1b749bSDharageswari R 14427a1b749bSDharageswari R } 14437a1b749bSDharageswari R 14447a1b749bSDharageswari R /* channel type enum map to number of chanels for that type */ 14457a1b749bSDharageswari R for (out_ch = 0; out_ch < ch_type; out_ch++) { 14467a1b749bSDharageswari R in_ch = list[out_ch]; 14477a1b749bSDharageswari R mic_cfg.blob[out_ch][in_ch] = SKL_DEFAULT_MIC_SEL_GAIN; 14487a1b749bSDharageswari R } 14497a1b749bSDharageswari R 14507a1b749bSDharageswari R return skl_fill_mic_sel_params(mconfig, &mic_cfg, w->dapm->dev); 14517a1b749bSDharageswari R } 14527a1b749bSDharageswari R 1453cfb0a873SVinod Koul /* 14548871dcb9SJeeja KP * Fill the dma id for host and link. In case of passthrough 14558871dcb9SJeeja KP * pipeline, this will both host and link in the same 14568871dcb9SJeeja KP * pipeline, so need to copy the link and host based on dev_type 14578871dcb9SJeeja KP */ 14588871dcb9SJeeja KP static void skl_tplg_fill_dma_id(struct skl_module_cfg *mcfg, 14598871dcb9SJeeja KP struct skl_pipe_params *params) 14608871dcb9SJeeja KP { 14618871dcb9SJeeja KP struct skl_pipe *pipe = mcfg->pipe; 14628871dcb9SJeeja KP 14638871dcb9SJeeja KP if (pipe->passthru) { 14648871dcb9SJeeja KP switch (mcfg->dev_type) { 14658871dcb9SJeeja KP case SKL_DEVICE_HDALINK: 14668871dcb9SJeeja KP pipe->p_params->link_dma_id = params->link_dma_id; 146712c3be0eSJeeja KP pipe->p_params->link_index = params->link_index; 14687f975a38SJeeja KP pipe->p_params->link_bps = params->link_bps; 14698871dcb9SJeeja KP break; 14708871dcb9SJeeja KP 14718871dcb9SJeeja KP case SKL_DEVICE_HDAHOST: 14728871dcb9SJeeja KP pipe->p_params->host_dma_id = params->host_dma_id; 14737f975a38SJeeja KP pipe->p_params->host_bps = params->host_bps; 14748871dcb9SJeeja KP break; 14758871dcb9SJeeja KP 14768871dcb9SJeeja KP default: 14778871dcb9SJeeja KP break; 14788871dcb9SJeeja KP } 14798871dcb9SJeeja KP pipe->p_params->s_fmt = params->s_fmt; 14808871dcb9SJeeja KP pipe->p_params->ch = params->ch; 14818871dcb9SJeeja KP pipe->p_params->s_freq = params->s_freq; 14828871dcb9SJeeja KP pipe->p_params->stream = params->stream; 148312c3be0eSJeeja KP pipe->p_params->format = params->format; 14848871dcb9SJeeja KP 14858871dcb9SJeeja KP } else { 14868871dcb9SJeeja KP memcpy(pipe->p_params, params, sizeof(*params)); 14878871dcb9SJeeja KP } 14888871dcb9SJeeja KP } 14898871dcb9SJeeja KP 14908871dcb9SJeeja KP /* 1491cfb0a873SVinod Koul * The FE params are passed by hw_params of the DAI. 1492cfb0a873SVinod Koul * On hw_params, the params are stored in Gateway module of the FE and we 1493cfb0a873SVinod Koul * need to calculate the format in DSP module configuration, that 1494cfb0a873SVinod Koul * conversion is done here 1495cfb0a873SVinod Koul */ 1496cfb0a873SVinod Koul int skl_tplg_update_pipe_params(struct device *dev, 1497cfb0a873SVinod Koul struct skl_module_cfg *mconfig, 1498cfb0a873SVinod Koul struct skl_pipe_params *params) 1499cfb0a873SVinod Koul { 1500cfb0a873SVinod Koul struct skl_module_fmt *format = NULL; 1501cfb0a873SVinod Koul 15028871dcb9SJeeja KP skl_tplg_fill_dma_id(mconfig, params); 1503cfb0a873SVinod Koul 1504cfb0a873SVinod Koul if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) 15054cd9899fSHardik T Shah format = &mconfig->in_fmt[0]; 1506cfb0a873SVinod Koul else 15074cd9899fSHardik T Shah format = &mconfig->out_fmt[0]; 1508cfb0a873SVinod Koul 1509cfb0a873SVinod Koul /* set the hw_params */ 1510cfb0a873SVinod Koul format->s_freq = params->s_freq; 1511cfb0a873SVinod Koul format->channels = params->ch; 1512cfb0a873SVinod Koul format->valid_bit_depth = skl_get_bit_depth(params->s_fmt); 1513cfb0a873SVinod Koul 1514cfb0a873SVinod Koul /* 1515cfb0a873SVinod Koul * 16 bit is 16 bit container whereas 24 bit is in 32 bit 1516cfb0a873SVinod Koul * container so update bit depth accordingly 1517cfb0a873SVinod Koul */ 1518cfb0a873SVinod Koul switch (format->valid_bit_depth) { 1519cfb0a873SVinod Koul case SKL_DEPTH_16BIT: 1520cfb0a873SVinod Koul format->bit_depth = format->valid_bit_depth; 1521cfb0a873SVinod Koul break; 1522cfb0a873SVinod Koul 1523cfb0a873SVinod Koul case SKL_DEPTH_24BIT: 15246654f39eSJeeja KP case SKL_DEPTH_32BIT: 1525cfb0a873SVinod Koul format->bit_depth = SKL_DEPTH_32BIT; 1526cfb0a873SVinod Koul break; 1527cfb0a873SVinod Koul 1528cfb0a873SVinod Koul default: 1529cfb0a873SVinod Koul dev_err(dev, "Invalid bit depth %x for pipe\n", 1530cfb0a873SVinod Koul format->valid_bit_depth); 1531cfb0a873SVinod Koul return -EINVAL; 1532cfb0a873SVinod Koul } 1533cfb0a873SVinod Koul 1534cfb0a873SVinod Koul if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) { 1535cfb0a873SVinod Koul mconfig->ibs = (format->s_freq / 1000) * 1536cfb0a873SVinod Koul (format->channels) * 1537cfb0a873SVinod Koul (format->bit_depth >> 3); 1538cfb0a873SVinod Koul } else { 1539cfb0a873SVinod Koul mconfig->obs = (format->s_freq / 1000) * 1540cfb0a873SVinod Koul (format->channels) * 1541cfb0a873SVinod Koul (format->bit_depth >> 3); 1542cfb0a873SVinod Koul } 1543cfb0a873SVinod Koul 1544cfb0a873SVinod Koul return 0; 1545cfb0a873SVinod Koul } 1546cfb0a873SVinod Koul 1547cfb0a873SVinod Koul /* 1548cfb0a873SVinod Koul * Query the module config for the FE DAI 1549cfb0a873SVinod Koul * This is used to find the hw_params set for that DAI and apply to FE 1550cfb0a873SVinod Koul * pipeline 1551cfb0a873SVinod Koul */ 1552cfb0a873SVinod Koul struct skl_module_cfg * 1553cfb0a873SVinod Koul skl_tplg_fe_get_cpr_module(struct snd_soc_dai *dai, int stream) 1554cfb0a873SVinod Koul { 1555cfb0a873SVinod Koul struct snd_soc_dapm_widget *w; 1556cfb0a873SVinod Koul struct snd_soc_dapm_path *p = NULL; 1557cfb0a873SVinod Koul 1558cfb0a873SVinod Koul if (stream == SNDRV_PCM_STREAM_PLAYBACK) { 1559cfb0a873SVinod Koul w = dai->playback_widget; 1560f0900eb2SSubhransu S. Prusty snd_soc_dapm_widget_for_each_sink_path(w, p) { 1561cfb0a873SVinod Koul if (p->connect && p->sink->power && 1562a28f51dbSJeeja KP !is_skl_dsp_widget_type(p->sink)) 1563cfb0a873SVinod Koul continue; 1564cfb0a873SVinod Koul 1565cfb0a873SVinod Koul if (p->sink->priv) { 1566cfb0a873SVinod Koul dev_dbg(dai->dev, "set params for %s\n", 1567cfb0a873SVinod Koul p->sink->name); 1568cfb0a873SVinod Koul return p->sink->priv; 1569cfb0a873SVinod Koul } 1570cfb0a873SVinod Koul } 1571cfb0a873SVinod Koul } else { 1572cfb0a873SVinod Koul w = dai->capture_widget; 1573f0900eb2SSubhransu S. Prusty snd_soc_dapm_widget_for_each_source_path(w, p) { 1574cfb0a873SVinod Koul if (p->connect && p->source->power && 1575a28f51dbSJeeja KP !is_skl_dsp_widget_type(p->source)) 1576cfb0a873SVinod Koul continue; 1577cfb0a873SVinod Koul 1578cfb0a873SVinod Koul if (p->source->priv) { 1579cfb0a873SVinod Koul dev_dbg(dai->dev, "set params for %s\n", 1580cfb0a873SVinod Koul p->source->name); 1581cfb0a873SVinod Koul return p->source->priv; 1582cfb0a873SVinod Koul } 1583cfb0a873SVinod Koul } 1584cfb0a873SVinod Koul } 1585cfb0a873SVinod Koul 1586cfb0a873SVinod Koul return NULL; 1587cfb0a873SVinod Koul } 1588cfb0a873SVinod Koul 1589718a42b5SDharageswari.R static struct skl_module_cfg *skl_get_mconfig_pb_cpr( 1590718a42b5SDharageswari.R struct snd_soc_dai *dai, struct snd_soc_dapm_widget *w) 1591718a42b5SDharageswari.R { 1592718a42b5SDharageswari.R struct snd_soc_dapm_path *p; 1593718a42b5SDharageswari.R struct skl_module_cfg *mconfig = NULL; 1594718a42b5SDharageswari.R 1595718a42b5SDharageswari.R snd_soc_dapm_widget_for_each_source_path(w, p) { 1596718a42b5SDharageswari.R if (w->endpoints[SND_SOC_DAPM_DIR_OUT] > 0) { 1597718a42b5SDharageswari.R if (p->connect && 1598718a42b5SDharageswari.R (p->sink->id == snd_soc_dapm_aif_out) && 1599718a42b5SDharageswari.R p->source->priv) { 1600718a42b5SDharageswari.R mconfig = p->source->priv; 1601718a42b5SDharageswari.R return mconfig; 1602718a42b5SDharageswari.R } 1603718a42b5SDharageswari.R mconfig = skl_get_mconfig_pb_cpr(dai, p->source); 1604718a42b5SDharageswari.R if (mconfig) 1605718a42b5SDharageswari.R return mconfig; 1606718a42b5SDharageswari.R } 1607718a42b5SDharageswari.R } 1608718a42b5SDharageswari.R return mconfig; 1609718a42b5SDharageswari.R } 1610718a42b5SDharageswari.R 1611718a42b5SDharageswari.R static struct skl_module_cfg *skl_get_mconfig_cap_cpr( 1612718a42b5SDharageswari.R struct snd_soc_dai *dai, struct snd_soc_dapm_widget *w) 1613718a42b5SDharageswari.R { 1614718a42b5SDharageswari.R struct snd_soc_dapm_path *p; 1615718a42b5SDharageswari.R struct skl_module_cfg *mconfig = NULL; 1616718a42b5SDharageswari.R 1617718a42b5SDharageswari.R snd_soc_dapm_widget_for_each_sink_path(w, p) { 1618718a42b5SDharageswari.R if (w->endpoints[SND_SOC_DAPM_DIR_IN] > 0) { 1619718a42b5SDharageswari.R if (p->connect && 1620718a42b5SDharageswari.R (p->source->id == snd_soc_dapm_aif_in) && 1621718a42b5SDharageswari.R p->sink->priv) { 1622718a42b5SDharageswari.R mconfig = p->sink->priv; 1623718a42b5SDharageswari.R return mconfig; 1624718a42b5SDharageswari.R } 1625718a42b5SDharageswari.R mconfig = skl_get_mconfig_cap_cpr(dai, p->sink); 1626718a42b5SDharageswari.R if (mconfig) 1627718a42b5SDharageswari.R return mconfig; 1628718a42b5SDharageswari.R } 1629718a42b5SDharageswari.R } 1630718a42b5SDharageswari.R return mconfig; 1631718a42b5SDharageswari.R } 1632718a42b5SDharageswari.R 1633718a42b5SDharageswari.R struct skl_module_cfg * 1634718a42b5SDharageswari.R skl_tplg_be_get_cpr_module(struct snd_soc_dai *dai, int stream) 1635718a42b5SDharageswari.R { 1636718a42b5SDharageswari.R struct snd_soc_dapm_widget *w; 1637718a42b5SDharageswari.R struct skl_module_cfg *mconfig; 1638718a42b5SDharageswari.R 1639718a42b5SDharageswari.R if (stream == SNDRV_PCM_STREAM_PLAYBACK) { 1640718a42b5SDharageswari.R w = dai->playback_widget; 1641718a42b5SDharageswari.R mconfig = skl_get_mconfig_pb_cpr(dai, w); 1642718a42b5SDharageswari.R } else { 1643718a42b5SDharageswari.R w = dai->capture_widget; 1644718a42b5SDharageswari.R mconfig = skl_get_mconfig_cap_cpr(dai, w); 1645718a42b5SDharageswari.R } 1646718a42b5SDharageswari.R return mconfig; 1647718a42b5SDharageswari.R } 1648718a42b5SDharageswari.R 1649cfb0a873SVinod Koul static u8 skl_tplg_be_link_type(int dev_type) 1650cfb0a873SVinod Koul { 1651cfb0a873SVinod Koul int ret; 1652cfb0a873SVinod Koul 1653cfb0a873SVinod Koul switch (dev_type) { 1654cfb0a873SVinod Koul case SKL_DEVICE_BT: 1655cfb0a873SVinod Koul ret = NHLT_LINK_SSP; 1656cfb0a873SVinod Koul break; 1657cfb0a873SVinod Koul 1658cfb0a873SVinod Koul case SKL_DEVICE_DMIC: 1659cfb0a873SVinod Koul ret = NHLT_LINK_DMIC; 1660cfb0a873SVinod Koul break; 1661cfb0a873SVinod Koul 1662cfb0a873SVinod Koul case SKL_DEVICE_I2S: 1663cfb0a873SVinod Koul ret = NHLT_LINK_SSP; 1664cfb0a873SVinod Koul break; 1665cfb0a873SVinod Koul 1666cfb0a873SVinod Koul case SKL_DEVICE_HDALINK: 1667cfb0a873SVinod Koul ret = NHLT_LINK_HDA; 1668cfb0a873SVinod Koul break; 1669cfb0a873SVinod Koul 1670cfb0a873SVinod Koul default: 1671cfb0a873SVinod Koul ret = NHLT_LINK_INVALID; 1672cfb0a873SVinod Koul break; 1673cfb0a873SVinod Koul } 1674cfb0a873SVinod Koul 1675cfb0a873SVinod Koul return ret; 1676cfb0a873SVinod Koul } 1677cfb0a873SVinod Koul 1678cfb0a873SVinod Koul /* 1679cfb0a873SVinod Koul * Fill the BE gateway parameters 1680cfb0a873SVinod Koul * The BE gateway expects a blob of parameters which are kept in the ACPI 1681cfb0a873SVinod Koul * NHLT blob, so query the blob for interface type (i2s/pdm) and instance. 1682cfb0a873SVinod Koul * The port can have multiple settings so pick based on the PCM 1683cfb0a873SVinod Koul * parameters 1684cfb0a873SVinod Koul */ 1685cfb0a873SVinod Koul static int skl_tplg_be_fill_pipe_params(struct snd_soc_dai *dai, 1686cfb0a873SVinod Koul struct skl_module_cfg *mconfig, 1687cfb0a873SVinod Koul struct skl_pipe_params *params) 1688cfb0a873SVinod Koul { 1689cfb0a873SVinod Koul struct nhlt_specific_cfg *cfg; 1690cfb0a873SVinod Koul struct skl *skl = get_skl_ctx(dai->dev); 1691cfb0a873SVinod Koul int link_type = skl_tplg_be_link_type(mconfig->dev_type); 1692db2f586bSSenthilnathan Veppur u8 dev_type = skl_tplg_be_dev_type(mconfig->dev_type); 1693cfb0a873SVinod Koul 16948871dcb9SJeeja KP skl_tplg_fill_dma_id(mconfig, params); 1695cfb0a873SVinod Koul 1696b30c275eSJeeja KP if (link_type == NHLT_LINK_HDA) 1697b30c275eSJeeja KP return 0; 1698b30c275eSJeeja KP 1699cfb0a873SVinod Koul /* update the blob based on virtual bus_id*/ 1700cfb0a873SVinod Koul cfg = skl_get_ep_blob(skl, mconfig->vbus_id, link_type, 1701cfb0a873SVinod Koul params->s_fmt, params->ch, 1702db2f586bSSenthilnathan Veppur params->s_freq, params->stream, 1703db2f586bSSenthilnathan Veppur dev_type); 1704cfb0a873SVinod Koul if (cfg) { 1705cfb0a873SVinod Koul mconfig->formats_config.caps_size = cfg->size; 1706bc03281aSJeeja KP mconfig->formats_config.caps = (u32 *) &cfg->caps; 1707cfb0a873SVinod Koul } else { 1708cfb0a873SVinod Koul dev_err(dai->dev, "Blob NULL for id %x type %d dirn %d\n", 1709cfb0a873SVinod Koul mconfig->vbus_id, link_type, 1710cfb0a873SVinod Koul params->stream); 1711cfb0a873SVinod Koul dev_err(dai->dev, "PCM: ch %d, freq %d, fmt %d\n", 1712cfb0a873SVinod Koul params->ch, params->s_freq, params->s_fmt); 1713cfb0a873SVinod Koul return -EINVAL; 1714cfb0a873SVinod Koul } 1715cfb0a873SVinod Koul 1716cfb0a873SVinod Koul return 0; 1717cfb0a873SVinod Koul } 1718cfb0a873SVinod Koul 1719cfb0a873SVinod Koul static int skl_tplg_be_set_src_pipe_params(struct snd_soc_dai *dai, 1720cfb0a873SVinod Koul struct snd_soc_dapm_widget *w, 1721cfb0a873SVinod Koul struct skl_pipe_params *params) 1722cfb0a873SVinod Koul { 1723cfb0a873SVinod Koul struct snd_soc_dapm_path *p; 17244d8adccbSSubhransu S. Prusty int ret = -EIO; 1725cfb0a873SVinod Koul 1726f0900eb2SSubhransu S. Prusty snd_soc_dapm_widget_for_each_source_path(w, p) { 1727cfb0a873SVinod Koul if (p->connect && is_skl_dsp_widget_type(p->source) && 1728cfb0a873SVinod Koul p->source->priv) { 1729cfb0a873SVinod Koul 17309a03cb49SJeeja KP ret = skl_tplg_be_fill_pipe_params(dai, 17319a03cb49SJeeja KP p->source->priv, params); 17324d8adccbSSubhransu S. Prusty if (ret < 0) 17334d8adccbSSubhransu S. Prusty return ret; 1734cfb0a873SVinod Koul } else { 17359a03cb49SJeeja KP ret = skl_tplg_be_set_src_pipe_params(dai, 17369a03cb49SJeeja KP p->source, params); 17374d8adccbSSubhransu S. Prusty if (ret < 0) 17384d8adccbSSubhransu S. Prusty return ret; 1739cfb0a873SVinod Koul } 1740cfb0a873SVinod Koul } 1741cfb0a873SVinod Koul 17424d8adccbSSubhransu S. Prusty return ret; 1743cfb0a873SVinod Koul } 1744cfb0a873SVinod Koul 1745cfb0a873SVinod Koul static int skl_tplg_be_set_sink_pipe_params(struct snd_soc_dai *dai, 1746cfb0a873SVinod Koul struct snd_soc_dapm_widget *w, struct skl_pipe_params *params) 1747cfb0a873SVinod Koul { 1748cfb0a873SVinod Koul struct snd_soc_dapm_path *p = NULL; 17494d8adccbSSubhransu S. Prusty int ret = -EIO; 1750cfb0a873SVinod Koul 1751f0900eb2SSubhransu S. Prusty snd_soc_dapm_widget_for_each_sink_path(w, p) { 1752cfb0a873SVinod Koul if (p->connect && is_skl_dsp_widget_type(p->sink) && 1753cfb0a873SVinod Koul p->sink->priv) { 1754cfb0a873SVinod Koul 17559a03cb49SJeeja KP ret = skl_tplg_be_fill_pipe_params(dai, 17569a03cb49SJeeja KP p->sink->priv, params); 17574d8adccbSSubhransu S. Prusty if (ret < 0) 17584d8adccbSSubhransu S. Prusty return ret; 17594d8adccbSSubhransu S. Prusty } else { 17604d8adccbSSubhransu S. Prusty ret = skl_tplg_be_set_sink_pipe_params( 1761cfb0a873SVinod Koul dai, p->sink, params); 17624d8adccbSSubhransu S. Prusty if (ret < 0) 17634d8adccbSSubhransu S. Prusty return ret; 1764cfb0a873SVinod Koul } 1765cfb0a873SVinod Koul } 1766cfb0a873SVinod Koul 17674d8adccbSSubhransu S. Prusty return ret; 1768cfb0a873SVinod Koul } 1769cfb0a873SVinod Koul 1770cfb0a873SVinod Koul /* 1771cfb0a873SVinod Koul * BE hw_params can be a source parameters (capture) or sink parameters 1772cfb0a873SVinod Koul * (playback). Based on sink and source we need to either find the source 1773cfb0a873SVinod Koul * list or the sink list and set the pipeline parameters 1774cfb0a873SVinod Koul */ 1775cfb0a873SVinod Koul int skl_tplg_be_update_params(struct snd_soc_dai *dai, 1776cfb0a873SVinod Koul struct skl_pipe_params *params) 1777cfb0a873SVinod Koul { 1778cfb0a873SVinod Koul struct snd_soc_dapm_widget *w; 1779cfb0a873SVinod Koul 1780cfb0a873SVinod Koul if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) { 1781cfb0a873SVinod Koul w = dai->playback_widget; 1782cfb0a873SVinod Koul 1783cfb0a873SVinod Koul return skl_tplg_be_set_src_pipe_params(dai, w, params); 1784cfb0a873SVinod Koul 1785cfb0a873SVinod Koul } else { 1786cfb0a873SVinod Koul w = dai->capture_widget; 1787cfb0a873SVinod Koul 1788cfb0a873SVinod Koul return skl_tplg_be_set_sink_pipe_params(dai, w, params); 1789cfb0a873SVinod Koul } 1790cfb0a873SVinod Koul 1791cfb0a873SVinod Koul return 0; 1792cfb0a873SVinod Koul } 17933af36706SVinod Koul 17943af36706SVinod Koul static const struct snd_soc_tplg_widget_events skl_tplg_widget_ops[] = { 17953af36706SVinod Koul {SKL_MIXER_EVENT, skl_tplg_mixer_event}, 17969a1e3507SVinod Koul {SKL_VMIXER_EVENT, skl_tplg_mixer_event}, 17973af36706SVinod Koul {SKL_PGA_EVENT, skl_tplg_pga_event}, 17983af36706SVinod Koul }; 17993af36706SVinod Koul 1800140adfbaSJeeja KP static const struct snd_soc_tplg_bytes_ext_ops skl_tlv_ops[] = { 1801140adfbaSJeeja KP {SKL_CONTROL_TYPE_BYTE_TLV, skl_tplg_tlv_control_get, 1802140adfbaSJeeja KP skl_tplg_tlv_control_set}, 1803140adfbaSJeeja KP }; 1804140adfbaSJeeja KP 18057a1b749bSDharageswari R static const struct snd_soc_tplg_kcontrol_ops skl_tplg_kcontrol_ops[] = { 18067a1b749bSDharageswari R { 18077a1b749bSDharageswari R .id = SKL_CONTROL_TYPE_MIC_SELECT, 18087a1b749bSDharageswari R .get = skl_tplg_mic_control_get, 18097a1b749bSDharageswari R .put = skl_tplg_mic_control_set, 18107a1b749bSDharageswari R }, 18117a1b749bSDharageswari R }; 18127a1b749bSDharageswari R 18136277e832SShreyas NC static int skl_tplg_fill_pipe_tkn(struct device *dev, 18146277e832SShreyas NC struct skl_pipe *pipe, u32 tkn, 18156277e832SShreyas NC u32 tkn_val) 18163af36706SVinod Koul { 18173af36706SVinod Koul 18186277e832SShreyas NC switch (tkn) { 18196277e832SShreyas NC case SKL_TKN_U32_PIPE_CONN_TYPE: 18206277e832SShreyas NC pipe->conn_type = tkn_val; 18216277e832SShreyas NC break; 18226277e832SShreyas NC 18236277e832SShreyas NC case SKL_TKN_U32_PIPE_PRIORITY: 18246277e832SShreyas NC pipe->pipe_priority = tkn_val; 18256277e832SShreyas NC break; 18266277e832SShreyas NC 18276277e832SShreyas NC case SKL_TKN_U32_PIPE_MEM_PGS: 18286277e832SShreyas NC pipe->memory_pages = tkn_val; 18296277e832SShreyas NC break; 18306277e832SShreyas NC 18318a0cb236SVinod Koul case SKL_TKN_U32_PMODE: 18328a0cb236SVinod Koul pipe->lp_mode = tkn_val; 18338a0cb236SVinod Koul break; 18348a0cb236SVinod Koul 18356277e832SShreyas NC default: 18366277e832SShreyas NC dev_err(dev, "Token not handled %d\n", tkn); 18376277e832SShreyas NC return -EINVAL; 18383af36706SVinod Koul } 18396277e832SShreyas NC 18406277e832SShreyas NC return 0; 18413af36706SVinod Koul } 18423af36706SVinod Koul 18433af36706SVinod Koul /* 18446277e832SShreyas NC * Add pipeline by parsing the relevant tokens 18456277e832SShreyas NC * Return an existing pipe if the pipe already exists. 18463af36706SVinod Koul */ 18476277e832SShreyas NC static int skl_tplg_add_pipe(struct device *dev, 18486277e832SShreyas NC struct skl_module_cfg *mconfig, struct skl *skl, 18496277e832SShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem) 18503af36706SVinod Koul { 18513af36706SVinod Koul struct skl_pipeline *ppl; 18523af36706SVinod Koul struct skl_pipe *pipe; 18533af36706SVinod Koul struct skl_pipe_params *params; 18543af36706SVinod Koul 18553af36706SVinod Koul list_for_each_entry(ppl, &skl->ppl_list, node) { 18566277e832SShreyas NC if (ppl->pipe->ppl_id == tkn_elem->value) { 18576277e832SShreyas NC mconfig->pipe = ppl->pipe; 1858081dc8abSGuneshwor Singh return -EEXIST; 18596277e832SShreyas NC } 18603af36706SVinod Koul } 18613af36706SVinod Koul 18623af36706SVinod Koul ppl = devm_kzalloc(dev, sizeof(*ppl), GFP_KERNEL); 18633af36706SVinod Koul if (!ppl) 18646277e832SShreyas NC return -ENOMEM; 18653af36706SVinod Koul 18663af36706SVinod Koul pipe = devm_kzalloc(dev, sizeof(*pipe), GFP_KERNEL); 18673af36706SVinod Koul if (!pipe) 18686277e832SShreyas NC return -ENOMEM; 18693af36706SVinod Koul 18703af36706SVinod Koul params = devm_kzalloc(dev, sizeof(*params), GFP_KERNEL); 18713af36706SVinod Koul if (!params) 18726277e832SShreyas NC return -ENOMEM; 18733af36706SVinod Koul 18743af36706SVinod Koul pipe->p_params = params; 18756277e832SShreyas NC pipe->ppl_id = tkn_elem->value; 18763af36706SVinod Koul INIT_LIST_HEAD(&pipe->w_list); 18773af36706SVinod Koul 18783af36706SVinod Koul ppl->pipe = pipe; 18793af36706SVinod Koul list_add(&ppl->node, &skl->ppl_list); 18803af36706SVinod Koul 18816277e832SShreyas NC mconfig->pipe = pipe; 18826277e832SShreyas NC mconfig->pipe->state = SKL_PIPE_INVALID; 18836277e832SShreyas NC 18846277e832SShreyas NC return 0; 18853af36706SVinod Koul } 18863af36706SVinod Koul 18876277e832SShreyas NC static int skl_tplg_fill_pin(struct device *dev, u32 tkn, 18886277e832SShreyas NC struct skl_module_pin *m_pin, 18896277e832SShreyas NC int pin_index, u32 value) 18906277e832SShreyas NC { 18916277e832SShreyas NC switch (tkn) { 18926277e832SShreyas NC case SKL_TKN_U32_PIN_MOD_ID: 18936277e832SShreyas NC m_pin[pin_index].id.module_id = value; 18946277e832SShreyas NC break; 18956277e832SShreyas NC 18966277e832SShreyas NC case SKL_TKN_U32_PIN_INST_ID: 18976277e832SShreyas NC m_pin[pin_index].id.instance_id = value; 18986277e832SShreyas NC break; 18996277e832SShreyas NC 19006277e832SShreyas NC default: 19016277e832SShreyas NC dev_err(dev, "%d Not a pin token\n", value); 19026277e832SShreyas NC return -EINVAL; 19036277e832SShreyas NC } 19046277e832SShreyas NC 19056277e832SShreyas NC return 0; 19066277e832SShreyas NC } 19076277e832SShreyas NC 19086277e832SShreyas NC /* 19096277e832SShreyas NC * Parse for pin config specific tokens to fill up the 19106277e832SShreyas NC * module private data 19116277e832SShreyas NC */ 19126277e832SShreyas NC static int skl_tplg_fill_pins_info(struct device *dev, 19136277e832SShreyas NC struct skl_module_cfg *mconfig, 19146277e832SShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem, 19156277e832SShreyas NC int dir, int pin_count) 19166277e832SShreyas NC { 19176277e832SShreyas NC int ret; 19186277e832SShreyas NC struct skl_module_pin *m_pin; 19196277e832SShreyas NC 19206277e832SShreyas NC switch (dir) { 19216277e832SShreyas NC case SKL_DIR_IN: 19226277e832SShreyas NC m_pin = mconfig->m_in_pin; 19236277e832SShreyas NC break; 19246277e832SShreyas NC 19256277e832SShreyas NC case SKL_DIR_OUT: 19266277e832SShreyas NC m_pin = mconfig->m_out_pin; 19276277e832SShreyas NC break; 19286277e832SShreyas NC 19296277e832SShreyas NC default: 1930ecd286a9SColin Ian King dev_err(dev, "Invalid direction value\n"); 19316277e832SShreyas NC return -EINVAL; 19326277e832SShreyas NC } 19336277e832SShreyas NC 19346277e832SShreyas NC ret = skl_tplg_fill_pin(dev, tkn_elem->token, 19356277e832SShreyas NC m_pin, pin_count, tkn_elem->value); 19366277e832SShreyas NC 19376277e832SShreyas NC if (ret < 0) 19386277e832SShreyas NC return ret; 19396277e832SShreyas NC 19406277e832SShreyas NC m_pin[pin_count].in_use = false; 19416277e832SShreyas NC m_pin[pin_count].pin_state = SKL_PIN_UNBIND; 19426277e832SShreyas NC 19436277e832SShreyas NC return 0; 19446277e832SShreyas NC } 19456277e832SShreyas NC 19466277e832SShreyas NC /* 19476277e832SShreyas NC * Fill up input/output module config format based 19486277e832SShreyas NC * on the direction 19496277e832SShreyas NC */ 19506277e832SShreyas NC static int skl_tplg_fill_fmt(struct device *dev, 1951ca312fdaSShreyas NC struct skl_module_fmt *dst_fmt, 1952ca312fdaSShreyas NC u32 tkn, u32 value) 19536277e832SShreyas NC { 19546277e832SShreyas NC switch (tkn) { 19556277e832SShreyas NC case SKL_TKN_U32_FMT_CH: 19566277e832SShreyas NC dst_fmt->channels = value; 19576277e832SShreyas NC break; 19586277e832SShreyas NC 19596277e832SShreyas NC case SKL_TKN_U32_FMT_FREQ: 19606277e832SShreyas NC dst_fmt->s_freq = value; 19616277e832SShreyas NC break; 19626277e832SShreyas NC 19636277e832SShreyas NC case SKL_TKN_U32_FMT_BIT_DEPTH: 19646277e832SShreyas NC dst_fmt->bit_depth = value; 19656277e832SShreyas NC break; 19666277e832SShreyas NC 19676277e832SShreyas NC case SKL_TKN_U32_FMT_SAMPLE_SIZE: 19686277e832SShreyas NC dst_fmt->valid_bit_depth = value; 19696277e832SShreyas NC break; 19706277e832SShreyas NC 19716277e832SShreyas NC case SKL_TKN_U32_FMT_CH_CONFIG: 19726277e832SShreyas NC dst_fmt->ch_cfg = value; 19736277e832SShreyas NC break; 19746277e832SShreyas NC 19756277e832SShreyas NC case SKL_TKN_U32_FMT_INTERLEAVE: 19766277e832SShreyas NC dst_fmt->interleaving_style = value; 19776277e832SShreyas NC break; 19786277e832SShreyas NC 19796277e832SShreyas NC case SKL_TKN_U32_FMT_SAMPLE_TYPE: 19806277e832SShreyas NC dst_fmt->sample_type = value; 19816277e832SShreyas NC break; 19826277e832SShreyas NC 19836277e832SShreyas NC case SKL_TKN_U32_FMT_CH_MAP: 19846277e832SShreyas NC dst_fmt->ch_map = value; 19856277e832SShreyas NC break; 19866277e832SShreyas NC 19876277e832SShreyas NC default: 1988ecd286a9SColin Ian King dev_err(dev, "Invalid token %d\n", tkn); 19896277e832SShreyas NC return -EINVAL; 19906277e832SShreyas NC } 19916277e832SShreyas NC 19926277e832SShreyas NC return 0; 19936277e832SShreyas NC } 19946277e832SShreyas NC 1995ca312fdaSShreyas NC static int skl_tplg_widget_fill_fmt(struct device *dev, 1996ca312fdaSShreyas NC struct skl_module_cfg *mconfig, 1997ca312fdaSShreyas NC u32 tkn, u32 val, u32 dir, int fmt_idx) 1998ca312fdaSShreyas NC { 1999ca312fdaSShreyas NC struct skl_module_fmt *dst_fmt; 2000ca312fdaSShreyas NC 2001ca312fdaSShreyas NC switch (dir) { 2002ca312fdaSShreyas NC case SKL_DIR_IN: 2003ca312fdaSShreyas NC dst_fmt = &mconfig->in_fmt[fmt_idx]; 2004ca312fdaSShreyas NC break; 2005ca312fdaSShreyas NC 2006ca312fdaSShreyas NC case SKL_DIR_OUT: 2007ca312fdaSShreyas NC dst_fmt = &mconfig->out_fmt[fmt_idx]; 2008ca312fdaSShreyas NC break; 2009ca312fdaSShreyas NC 2010ca312fdaSShreyas NC default: 2011ca312fdaSShreyas NC dev_err(dev, "Invalid direction: %d\n", dir); 2012ca312fdaSShreyas NC return -EINVAL; 2013ca312fdaSShreyas NC } 2014ca312fdaSShreyas NC 2015ca312fdaSShreyas NC return skl_tplg_fill_fmt(dev, dst_fmt, tkn, val); 2016ca312fdaSShreyas NC } 2017ca312fdaSShreyas NC 20186277e832SShreyas NC static int skl_tplg_get_uuid(struct device *dev, struct skl_module_cfg *mconfig, 20196277e832SShreyas NC struct snd_soc_tplg_vendor_uuid_elem *uuid_tkn) 20206277e832SShreyas NC { 20216277e832SShreyas NC if (uuid_tkn->token == SKL_TKN_UUID) 20226277e832SShreyas NC memcpy(&mconfig->guid, &uuid_tkn->uuid, 16); 20236277e832SShreyas NC else { 2024ecd286a9SColin Ian King dev_err(dev, "Not an UUID token tkn %d\n", uuid_tkn->token); 20256277e832SShreyas NC return -EINVAL; 20266277e832SShreyas NC } 20276277e832SShreyas NC 20286277e832SShreyas NC return 0; 20296277e832SShreyas NC } 20306277e832SShreyas NC 20316277e832SShreyas NC static void skl_tplg_fill_pin_dynamic_val( 20326277e832SShreyas NC struct skl_module_pin *mpin, u32 pin_count, u32 value) 20334cd9899fSHardik T Shah { 20344cd9899fSHardik T Shah int i; 20354cd9899fSHardik T Shah 20366277e832SShreyas NC for (i = 0; i < pin_count; i++) 20376277e832SShreyas NC mpin[i].is_dynamic = value; 20384cd9899fSHardik T Shah } 20396277e832SShreyas NC 20406277e832SShreyas NC /* 2041*db6ed55dSShreyas NC * Resource table in the manifest has pin specific resources 2042*db6ed55dSShreyas NC * like pin and pin buffer size 2043*db6ed55dSShreyas NC */ 2044*db6ed55dSShreyas NC static int skl_tplg_manifest_pin_res_tkn(struct device *dev, 2045*db6ed55dSShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem, 2046*db6ed55dSShreyas NC struct skl_module_res *res, int pin_idx, int dir) 2047*db6ed55dSShreyas NC { 2048*db6ed55dSShreyas NC struct skl_module_pin_resources *m_pin; 2049*db6ed55dSShreyas NC 2050*db6ed55dSShreyas NC switch (dir) { 2051*db6ed55dSShreyas NC case SKL_DIR_IN: 2052*db6ed55dSShreyas NC m_pin = &res->input[pin_idx]; 2053*db6ed55dSShreyas NC break; 2054*db6ed55dSShreyas NC 2055*db6ed55dSShreyas NC case SKL_DIR_OUT: 2056*db6ed55dSShreyas NC m_pin = &res->output[pin_idx]; 2057*db6ed55dSShreyas NC break; 2058*db6ed55dSShreyas NC 2059*db6ed55dSShreyas NC default: 2060*db6ed55dSShreyas NC dev_err(dev, "Invalid pin direction: %d\n", dir); 2061*db6ed55dSShreyas NC return -EINVAL; 2062*db6ed55dSShreyas NC } 2063*db6ed55dSShreyas NC 2064*db6ed55dSShreyas NC switch (tkn_elem->token) { 2065*db6ed55dSShreyas NC case SKL_TKN_MM_U32_RES_PIN_ID: 2066*db6ed55dSShreyas NC m_pin->pin_index = tkn_elem->value; 2067*db6ed55dSShreyas NC break; 2068*db6ed55dSShreyas NC 2069*db6ed55dSShreyas NC case SKL_TKN_MM_U32_PIN_BUF: 2070*db6ed55dSShreyas NC m_pin->buf_size = tkn_elem->value; 2071*db6ed55dSShreyas NC break; 2072*db6ed55dSShreyas NC 2073*db6ed55dSShreyas NC default: 2074*db6ed55dSShreyas NC dev_err(dev, "Invalid token: %d\n", tkn_elem->token); 2075*db6ed55dSShreyas NC return -EINVAL; 2076*db6ed55dSShreyas NC } 2077*db6ed55dSShreyas NC 2078*db6ed55dSShreyas NC return 0; 2079*db6ed55dSShreyas NC } 2080*db6ed55dSShreyas NC 2081*db6ed55dSShreyas NC /* 2082*db6ed55dSShreyas NC * Fill module specific resources from the manifest's resource 2083*db6ed55dSShreyas NC * table like CPS, DMA size, mem_pages. 2084*db6ed55dSShreyas NC */ 2085*db6ed55dSShreyas NC static int skl_tplg_fill_res_tkn(struct device *dev, 2086*db6ed55dSShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem, 2087*db6ed55dSShreyas NC struct skl_module_res *res, 2088*db6ed55dSShreyas NC int pin_idx, int dir) 2089*db6ed55dSShreyas NC { 2090*db6ed55dSShreyas NC int ret, tkn_count = 0; 2091*db6ed55dSShreyas NC 2092*db6ed55dSShreyas NC if (!res) 2093*db6ed55dSShreyas NC return -EINVAL; 2094*db6ed55dSShreyas NC 2095*db6ed55dSShreyas NC switch (tkn_elem->token) { 2096*db6ed55dSShreyas NC case SKL_TKN_MM_U32_CPS: 2097*db6ed55dSShreyas NC res->cps = tkn_elem->value; 2098*db6ed55dSShreyas NC break; 2099*db6ed55dSShreyas NC 2100*db6ed55dSShreyas NC case SKL_TKN_MM_U32_DMA_SIZE: 2101*db6ed55dSShreyas NC res->dma_buffer_size = tkn_elem->value; 2102*db6ed55dSShreyas NC break; 2103*db6ed55dSShreyas NC 2104*db6ed55dSShreyas NC case SKL_TKN_MM_U32_CPC: 2105*db6ed55dSShreyas NC res->cpc = tkn_elem->value; 2106*db6ed55dSShreyas NC break; 2107*db6ed55dSShreyas NC 2108*db6ed55dSShreyas NC case SKL_TKN_U32_MEM_PAGES: 2109*db6ed55dSShreyas NC res->is_pages = tkn_elem->value; 2110*db6ed55dSShreyas NC break; 2111*db6ed55dSShreyas NC 2112*db6ed55dSShreyas NC case SKL_TKN_U32_OBS: 2113*db6ed55dSShreyas NC res->obs = tkn_elem->value; 2114*db6ed55dSShreyas NC break; 2115*db6ed55dSShreyas NC 2116*db6ed55dSShreyas NC case SKL_TKN_U32_IBS: 2117*db6ed55dSShreyas NC res->ibs = tkn_elem->value; 2118*db6ed55dSShreyas NC break; 2119*db6ed55dSShreyas NC 2120*db6ed55dSShreyas NC case SKL_TKN_MM_U32_RES_PIN_ID: 2121*db6ed55dSShreyas NC case SKL_TKN_MM_U32_PIN_BUF: 2122*db6ed55dSShreyas NC ret = skl_tplg_manifest_pin_res_tkn(dev, tkn_elem, res, 2123*db6ed55dSShreyas NC pin_idx, dir); 2124*db6ed55dSShreyas NC if (ret < 0) 2125*db6ed55dSShreyas NC return ret; 2126*db6ed55dSShreyas NC break; 2127*db6ed55dSShreyas NC 2128*db6ed55dSShreyas NC default: 2129*db6ed55dSShreyas NC dev_err(dev, "Not a res type token: %d", tkn_elem->token); 2130*db6ed55dSShreyas NC return -EINVAL; 2131*db6ed55dSShreyas NC 2132*db6ed55dSShreyas NC } 2133*db6ed55dSShreyas NC tkn_count++; 2134*db6ed55dSShreyas NC 2135*db6ed55dSShreyas NC return tkn_count; 2136*db6ed55dSShreyas NC } 2137*db6ed55dSShreyas NC 2138*db6ed55dSShreyas NC /* 21396277e832SShreyas NC * Parse tokens to fill up the module private data 21406277e832SShreyas NC */ 21416277e832SShreyas NC static int skl_tplg_get_token(struct device *dev, 21426277e832SShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem, 21436277e832SShreyas NC struct skl *skl, struct skl_module_cfg *mconfig) 21446277e832SShreyas NC { 21456277e832SShreyas NC int tkn_count = 0; 21466277e832SShreyas NC int ret; 21476277e832SShreyas NC static int is_pipe_exists; 21486277e832SShreyas NC static int pin_index, dir; 21496277e832SShreyas NC 21506277e832SShreyas NC if (tkn_elem->token > SKL_TKN_MAX) 21516277e832SShreyas NC return -EINVAL; 21526277e832SShreyas NC 21536277e832SShreyas NC switch (tkn_elem->token) { 21546277e832SShreyas NC case SKL_TKN_U8_IN_QUEUE_COUNT: 21556277e832SShreyas NC mconfig->max_in_queue = tkn_elem->value; 21566277e832SShreyas NC mconfig->m_in_pin = devm_kzalloc(dev, mconfig->max_in_queue * 21576277e832SShreyas NC sizeof(*mconfig->m_in_pin), 21586277e832SShreyas NC GFP_KERNEL); 21596277e832SShreyas NC if (!mconfig->m_in_pin) 21606277e832SShreyas NC return -ENOMEM; 21616277e832SShreyas NC 21626277e832SShreyas NC break; 21636277e832SShreyas NC 21646277e832SShreyas NC case SKL_TKN_U8_OUT_QUEUE_COUNT: 21656277e832SShreyas NC mconfig->max_out_queue = tkn_elem->value; 21666277e832SShreyas NC mconfig->m_out_pin = devm_kzalloc(dev, mconfig->max_out_queue * 21676277e832SShreyas NC sizeof(*mconfig->m_out_pin), 21686277e832SShreyas NC GFP_KERNEL); 21696277e832SShreyas NC 21706277e832SShreyas NC if (!mconfig->m_out_pin) 21716277e832SShreyas NC return -ENOMEM; 21726277e832SShreyas NC 21736277e832SShreyas NC break; 21746277e832SShreyas NC 21756277e832SShreyas NC case SKL_TKN_U8_DYN_IN_PIN: 21766277e832SShreyas NC if (!mconfig->m_in_pin) 21776277e832SShreyas NC return -ENOMEM; 21786277e832SShreyas NC 21796277e832SShreyas NC skl_tplg_fill_pin_dynamic_val(mconfig->m_in_pin, 21806277e832SShreyas NC mconfig->max_in_queue, tkn_elem->value); 21816277e832SShreyas NC 21826277e832SShreyas NC break; 21836277e832SShreyas NC 21846277e832SShreyas NC case SKL_TKN_U8_DYN_OUT_PIN: 21856277e832SShreyas NC if (!mconfig->m_out_pin) 21866277e832SShreyas NC return -ENOMEM; 21876277e832SShreyas NC 21886277e832SShreyas NC skl_tplg_fill_pin_dynamic_val(mconfig->m_out_pin, 21896277e832SShreyas NC mconfig->max_out_queue, tkn_elem->value); 21906277e832SShreyas NC 21916277e832SShreyas NC break; 21926277e832SShreyas NC 21936277e832SShreyas NC case SKL_TKN_U8_TIME_SLOT: 21946277e832SShreyas NC mconfig->time_slot = tkn_elem->value; 21956277e832SShreyas NC break; 21966277e832SShreyas NC 21976277e832SShreyas NC case SKL_TKN_U8_CORE_ID: 21986277e832SShreyas NC mconfig->core_id = tkn_elem->value; 21996277e832SShreyas NC 22006277e832SShreyas NC case SKL_TKN_U8_MOD_TYPE: 22016277e832SShreyas NC mconfig->m_type = tkn_elem->value; 22026277e832SShreyas NC break; 22036277e832SShreyas NC 22046277e832SShreyas NC case SKL_TKN_U8_DEV_TYPE: 22056277e832SShreyas NC mconfig->dev_type = tkn_elem->value; 22066277e832SShreyas NC break; 22076277e832SShreyas NC 22086277e832SShreyas NC case SKL_TKN_U8_HW_CONN_TYPE: 22096277e832SShreyas NC mconfig->hw_conn_type = tkn_elem->value; 22106277e832SShreyas NC break; 22116277e832SShreyas NC 22126277e832SShreyas NC case SKL_TKN_U16_MOD_INST_ID: 22136277e832SShreyas NC mconfig->id.instance_id = 22146277e832SShreyas NC tkn_elem->value; 22156277e832SShreyas NC break; 22166277e832SShreyas NC 22176277e832SShreyas NC case SKL_TKN_U32_MEM_PAGES: 22186277e832SShreyas NC mconfig->mem_pages = tkn_elem->value; 22196277e832SShreyas NC break; 22206277e832SShreyas NC 22216277e832SShreyas NC case SKL_TKN_U32_MAX_MCPS: 22226277e832SShreyas NC mconfig->mcps = tkn_elem->value; 22236277e832SShreyas NC break; 22246277e832SShreyas NC 22256277e832SShreyas NC case SKL_TKN_U32_OBS: 22266277e832SShreyas NC mconfig->obs = tkn_elem->value; 22276277e832SShreyas NC break; 22286277e832SShreyas NC 22296277e832SShreyas NC case SKL_TKN_U32_IBS: 22306277e832SShreyas NC mconfig->ibs = tkn_elem->value; 22316277e832SShreyas NC break; 22326277e832SShreyas NC 22336277e832SShreyas NC case SKL_TKN_U32_VBUS_ID: 22346277e832SShreyas NC mconfig->vbus_id = tkn_elem->value; 22356277e832SShreyas NC break; 22366277e832SShreyas NC 22376277e832SShreyas NC case SKL_TKN_U32_PARAMS_FIXUP: 22386277e832SShreyas NC mconfig->params_fixup = tkn_elem->value; 22396277e832SShreyas NC break; 22406277e832SShreyas NC 22416277e832SShreyas NC case SKL_TKN_U32_CONVERTER: 22426277e832SShreyas NC mconfig->converter = tkn_elem->value; 22436277e832SShreyas NC break; 22446277e832SShreyas NC 2245c0116be3SSubhransu S. Prusty case SKL_TKN_U32_D0I3_CAPS: 22466bd9dcf3SVinod Koul mconfig->d0i3_caps = tkn_elem->value; 22476bd9dcf3SVinod Koul break; 22486bd9dcf3SVinod Koul 22496277e832SShreyas NC case SKL_TKN_U32_PIPE_ID: 22506277e832SShreyas NC ret = skl_tplg_add_pipe(dev, 22516277e832SShreyas NC mconfig, skl, tkn_elem); 22526277e832SShreyas NC 2253081dc8abSGuneshwor Singh if (ret < 0) { 2254081dc8abSGuneshwor Singh if (ret == -EEXIST) { 22556277e832SShreyas NC is_pipe_exists = 1; 2256081dc8abSGuneshwor Singh break; 2257081dc8abSGuneshwor Singh } 2258081dc8abSGuneshwor Singh return is_pipe_exists; 2259081dc8abSGuneshwor Singh } 22606277e832SShreyas NC 22616277e832SShreyas NC break; 22626277e832SShreyas NC 22636277e832SShreyas NC case SKL_TKN_U32_PIPE_CONN_TYPE: 22646277e832SShreyas NC case SKL_TKN_U32_PIPE_PRIORITY: 22656277e832SShreyas NC case SKL_TKN_U32_PIPE_MEM_PGS: 22668a0cb236SVinod Koul case SKL_TKN_U32_PMODE: 22676277e832SShreyas NC if (is_pipe_exists) { 22686277e832SShreyas NC ret = skl_tplg_fill_pipe_tkn(dev, mconfig->pipe, 22696277e832SShreyas NC tkn_elem->token, tkn_elem->value); 22706277e832SShreyas NC if (ret < 0) 22716277e832SShreyas NC return ret; 22726277e832SShreyas NC } 22736277e832SShreyas NC 22746277e832SShreyas NC break; 22756277e832SShreyas NC 22766277e832SShreyas NC /* 22776277e832SShreyas NC * SKL_TKN_U32_DIR_PIN_COUNT token has the value for both 22786277e832SShreyas NC * direction and the pin count. The first four bits represent 22796277e832SShreyas NC * direction and next four the pin count. 22806277e832SShreyas NC */ 22816277e832SShreyas NC case SKL_TKN_U32_DIR_PIN_COUNT: 22826277e832SShreyas NC dir = tkn_elem->value & SKL_IN_DIR_BIT_MASK; 22836277e832SShreyas NC pin_index = (tkn_elem->value & 22846277e832SShreyas NC SKL_PIN_COUNT_MASK) >> 4; 22856277e832SShreyas NC 22866277e832SShreyas NC break; 22876277e832SShreyas NC 22886277e832SShreyas NC case SKL_TKN_U32_FMT_CH: 22896277e832SShreyas NC case SKL_TKN_U32_FMT_FREQ: 22906277e832SShreyas NC case SKL_TKN_U32_FMT_BIT_DEPTH: 22916277e832SShreyas NC case SKL_TKN_U32_FMT_SAMPLE_SIZE: 22926277e832SShreyas NC case SKL_TKN_U32_FMT_CH_CONFIG: 22936277e832SShreyas NC case SKL_TKN_U32_FMT_INTERLEAVE: 22946277e832SShreyas NC case SKL_TKN_U32_FMT_SAMPLE_TYPE: 22956277e832SShreyas NC case SKL_TKN_U32_FMT_CH_MAP: 2296ca312fdaSShreyas NC ret = skl_tplg_widget_fill_fmt(dev, mconfig, tkn_elem->token, 22976277e832SShreyas NC tkn_elem->value, dir, pin_index); 22986277e832SShreyas NC 22996277e832SShreyas NC if (ret < 0) 23006277e832SShreyas NC return ret; 23016277e832SShreyas NC 23026277e832SShreyas NC break; 23036277e832SShreyas NC 23046277e832SShreyas NC case SKL_TKN_U32_PIN_MOD_ID: 23056277e832SShreyas NC case SKL_TKN_U32_PIN_INST_ID: 23066277e832SShreyas NC ret = skl_tplg_fill_pins_info(dev, 23076277e832SShreyas NC mconfig, tkn_elem, dir, 23086277e832SShreyas NC pin_index); 23096277e832SShreyas NC if (ret < 0) 23106277e832SShreyas NC return ret; 23116277e832SShreyas NC 23126277e832SShreyas NC break; 23136277e832SShreyas NC 23146277e832SShreyas NC case SKL_TKN_U32_CAPS_SIZE: 23156277e832SShreyas NC mconfig->formats_config.caps_size = 23166277e832SShreyas NC tkn_elem->value; 23176277e832SShreyas NC 23186277e832SShreyas NC break; 23196277e832SShreyas NC 2320133e6e5cSShreyas NC case SKL_TKN_U32_CAPS_SET_PARAMS: 2321133e6e5cSShreyas NC mconfig->formats_config.set_params = 2322133e6e5cSShreyas NC tkn_elem->value; 2323133e6e5cSShreyas NC break; 2324133e6e5cSShreyas NC 2325133e6e5cSShreyas NC case SKL_TKN_U32_CAPS_PARAMS_ID: 2326133e6e5cSShreyas NC mconfig->formats_config.param_id = 2327133e6e5cSShreyas NC tkn_elem->value; 2328133e6e5cSShreyas NC break; 2329133e6e5cSShreyas NC 23306277e832SShreyas NC case SKL_TKN_U32_PROC_DOMAIN: 23316277e832SShreyas NC mconfig->domain = 23326277e832SShreyas NC tkn_elem->value; 23336277e832SShreyas NC 23346277e832SShreyas NC break; 23356277e832SShreyas NC 2336939df3adSRamesh Babu case SKL_TKN_U32_DMA_BUF_SIZE: 2337939df3adSRamesh Babu mconfig->dma_buffer_size = tkn_elem->value; 2338939df3adSRamesh Babu break; 2339939df3adSRamesh Babu 23406277e832SShreyas NC case SKL_TKN_U8_IN_PIN_TYPE: 23416277e832SShreyas NC case SKL_TKN_U8_OUT_PIN_TYPE: 23426277e832SShreyas NC case SKL_TKN_U8_CONN_TYPE: 23436277e832SShreyas NC break; 23446277e832SShreyas NC 23456277e832SShreyas NC default: 23466277e832SShreyas NC dev_err(dev, "Token %d not handled\n", 23476277e832SShreyas NC tkn_elem->token); 23486277e832SShreyas NC return -EINVAL; 23496277e832SShreyas NC } 23506277e832SShreyas NC 23516277e832SShreyas NC tkn_count++; 23526277e832SShreyas NC 23536277e832SShreyas NC return tkn_count; 23546277e832SShreyas NC } 23556277e832SShreyas NC 23566277e832SShreyas NC /* 23576277e832SShreyas NC * Parse the vendor array for specific tokens to construct 23586277e832SShreyas NC * module private data 23596277e832SShreyas NC */ 23606277e832SShreyas NC static int skl_tplg_get_tokens(struct device *dev, 23616277e832SShreyas NC char *pvt_data, struct skl *skl, 23626277e832SShreyas NC struct skl_module_cfg *mconfig, int block_size) 23636277e832SShreyas NC { 23646277e832SShreyas NC struct snd_soc_tplg_vendor_array *array; 23656277e832SShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem; 23666277e832SShreyas NC int tkn_count = 0, ret; 23676277e832SShreyas NC int off = 0, tuple_size = 0; 23686277e832SShreyas NC 23696277e832SShreyas NC if (block_size <= 0) 23706277e832SShreyas NC return -EINVAL; 23716277e832SShreyas NC 23726277e832SShreyas NC while (tuple_size < block_size) { 23736277e832SShreyas NC array = (struct snd_soc_tplg_vendor_array *)(pvt_data + off); 23746277e832SShreyas NC 23756277e832SShreyas NC off += array->size; 23766277e832SShreyas NC 23776277e832SShreyas NC switch (array->type) { 23786277e832SShreyas NC case SND_SOC_TPLG_TUPLE_TYPE_STRING: 2379ecd286a9SColin Ian King dev_warn(dev, "no string tokens expected for skl tplg\n"); 23806277e832SShreyas NC continue; 23816277e832SShreyas NC 23826277e832SShreyas NC case SND_SOC_TPLG_TUPLE_TYPE_UUID: 23836277e832SShreyas NC ret = skl_tplg_get_uuid(dev, mconfig, array->uuid); 23846277e832SShreyas NC if (ret < 0) 23856277e832SShreyas NC return ret; 23866277e832SShreyas NC 23876277e832SShreyas NC tuple_size += sizeof(*array->uuid); 23886277e832SShreyas NC 23896277e832SShreyas NC continue; 23906277e832SShreyas NC 23916277e832SShreyas NC default: 23926277e832SShreyas NC tkn_elem = array->value; 23936277e832SShreyas NC tkn_count = 0; 23946277e832SShreyas NC break; 23956277e832SShreyas NC } 23966277e832SShreyas NC 23976277e832SShreyas NC while (tkn_count <= (array->num_elems - 1)) { 23986277e832SShreyas NC ret = skl_tplg_get_token(dev, tkn_elem, 23996277e832SShreyas NC skl, mconfig); 24006277e832SShreyas NC 24016277e832SShreyas NC if (ret < 0) 24026277e832SShreyas NC return ret; 24036277e832SShreyas NC 24046277e832SShreyas NC tkn_count = tkn_count + ret; 24056277e832SShreyas NC tkn_elem++; 24066277e832SShreyas NC } 24076277e832SShreyas NC 24086277e832SShreyas NC tuple_size += tkn_count * sizeof(*tkn_elem); 24096277e832SShreyas NC } 24106277e832SShreyas NC 2411133e6e5cSShreyas NC return off; 24126277e832SShreyas NC } 24136277e832SShreyas NC 24146277e832SShreyas NC /* 24156277e832SShreyas NC * Every data block is preceded by a descriptor to read the number 24166277e832SShreyas NC * of data blocks, they type of the block and it's size 24176277e832SShreyas NC */ 24186277e832SShreyas NC static int skl_tplg_get_desc_blocks(struct device *dev, 24196277e832SShreyas NC struct snd_soc_tplg_vendor_array *array) 24206277e832SShreyas NC { 24216277e832SShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem; 24226277e832SShreyas NC 24236277e832SShreyas NC tkn_elem = array->value; 24246277e832SShreyas NC 24256277e832SShreyas NC switch (tkn_elem->token) { 24266277e832SShreyas NC case SKL_TKN_U8_NUM_BLOCKS: 24276277e832SShreyas NC case SKL_TKN_U8_BLOCK_TYPE: 24286277e832SShreyas NC case SKL_TKN_U16_BLOCK_SIZE: 24296277e832SShreyas NC return tkn_elem->value; 24306277e832SShreyas NC 24316277e832SShreyas NC default: 2432ecd286a9SColin Ian King dev_err(dev, "Invalid descriptor token %d\n", tkn_elem->token); 24336277e832SShreyas NC break; 24346277e832SShreyas NC } 24356277e832SShreyas NC 24366277e832SShreyas NC return -EINVAL; 24376277e832SShreyas NC } 24386277e832SShreyas NC 24396277e832SShreyas NC /* 24406277e832SShreyas NC * Parse the private data for the token and corresponding value. 24416277e832SShreyas NC * The private data can have multiple data blocks. So, a data block 24426277e832SShreyas NC * is preceded by a descriptor for number of blocks and a descriptor 24436277e832SShreyas NC * for the type and size of the suceeding data block. 24446277e832SShreyas NC */ 24456277e832SShreyas NC static int skl_tplg_get_pvt_data(struct snd_soc_tplg_dapm_widget *tplg_w, 24466277e832SShreyas NC struct skl *skl, struct device *dev, 24476277e832SShreyas NC struct skl_module_cfg *mconfig) 24486277e832SShreyas NC { 24496277e832SShreyas NC struct snd_soc_tplg_vendor_array *array; 24506277e832SShreyas NC int num_blocks, block_size = 0, block_type, off = 0; 24516277e832SShreyas NC char *data; 24526277e832SShreyas NC int ret; 24536277e832SShreyas NC 24546277e832SShreyas NC /* Read the NUM_DATA_BLOCKS descriptor */ 24556277e832SShreyas NC array = (struct snd_soc_tplg_vendor_array *)tplg_w->priv.data; 24566277e832SShreyas NC ret = skl_tplg_get_desc_blocks(dev, array); 24576277e832SShreyas NC if (ret < 0) 24586277e832SShreyas NC return ret; 24596277e832SShreyas NC num_blocks = ret; 24606277e832SShreyas NC 24616277e832SShreyas NC off += array->size; 24626277e832SShreyas NC /* Read the BLOCK_TYPE and BLOCK_SIZE descriptor */ 24636277e832SShreyas NC while (num_blocks > 0) { 2464133e6e5cSShreyas NC array = (struct snd_soc_tplg_vendor_array *) 2465133e6e5cSShreyas NC (tplg_w->priv.data + off); 2466133e6e5cSShreyas NC 24676277e832SShreyas NC ret = skl_tplg_get_desc_blocks(dev, array); 24686277e832SShreyas NC 24696277e832SShreyas NC if (ret < 0) 24706277e832SShreyas NC return ret; 24716277e832SShreyas NC block_type = ret; 24726277e832SShreyas NC off += array->size; 24736277e832SShreyas NC 24746277e832SShreyas NC array = (struct snd_soc_tplg_vendor_array *) 24756277e832SShreyas NC (tplg_w->priv.data + off); 24766277e832SShreyas NC 24776277e832SShreyas NC ret = skl_tplg_get_desc_blocks(dev, array); 24786277e832SShreyas NC 24796277e832SShreyas NC if (ret < 0) 24806277e832SShreyas NC return ret; 24816277e832SShreyas NC block_size = ret; 24826277e832SShreyas NC off += array->size; 24836277e832SShreyas NC 24846277e832SShreyas NC array = (struct snd_soc_tplg_vendor_array *) 24856277e832SShreyas NC (tplg_w->priv.data + off); 24866277e832SShreyas NC 24876277e832SShreyas NC data = (tplg_w->priv.data + off); 24886277e832SShreyas NC 24896277e832SShreyas NC if (block_type == SKL_TYPE_TUPLE) { 24906277e832SShreyas NC ret = skl_tplg_get_tokens(dev, data, 24916277e832SShreyas NC skl, mconfig, block_size); 24926277e832SShreyas NC 24936277e832SShreyas NC if (ret < 0) 24946277e832SShreyas NC return ret; 24956277e832SShreyas NC 24966277e832SShreyas NC --num_blocks; 24976277e832SShreyas NC } else { 24986277e832SShreyas NC if (mconfig->formats_config.caps_size > 0) 24996277e832SShreyas NC memcpy(mconfig->formats_config.caps, data, 25006277e832SShreyas NC mconfig->formats_config.caps_size); 25016277e832SShreyas NC --num_blocks; 2502133e6e5cSShreyas NC ret = mconfig->formats_config.caps_size; 25036277e832SShreyas NC } 2504133e6e5cSShreyas NC off += ret; 25056277e832SShreyas NC } 25066277e832SShreyas NC 25076277e832SShreyas NC return 0; 25084cd9899fSHardik T Shah } 25094cd9899fSHardik T Shah 2510fe3f4442SDharageswari R static void skl_clear_pin_config(struct snd_soc_platform *platform, 2511fe3f4442SDharageswari R struct snd_soc_dapm_widget *w) 2512fe3f4442SDharageswari R { 2513fe3f4442SDharageswari R int i; 2514fe3f4442SDharageswari R struct skl_module_cfg *mconfig; 2515fe3f4442SDharageswari R struct skl_pipe *pipe; 2516fe3f4442SDharageswari R 2517fe3f4442SDharageswari R if (!strncmp(w->dapm->component->name, platform->component.name, 2518fe3f4442SDharageswari R strlen(platform->component.name))) { 2519fe3f4442SDharageswari R mconfig = w->priv; 2520fe3f4442SDharageswari R pipe = mconfig->pipe; 2521fe3f4442SDharageswari R for (i = 0; i < mconfig->max_in_queue; i++) { 2522fe3f4442SDharageswari R mconfig->m_in_pin[i].in_use = false; 2523fe3f4442SDharageswari R mconfig->m_in_pin[i].pin_state = SKL_PIN_UNBIND; 2524fe3f4442SDharageswari R } 2525fe3f4442SDharageswari R for (i = 0; i < mconfig->max_out_queue; i++) { 2526fe3f4442SDharageswari R mconfig->m_out_pin[i].in_use = false; 2527fe3f4442SDharageswari R mconfig->m_out_pin[i].pin_state = SKL_PIN_UNBIND; 2528fe3f4442SDharageswari R } 2529fe3f4442SDharageswari R pipe->state = SKL_PIPE_INVALID; 2530fe3f4442SDharageswari R mconfig->m_state = SKL_MODULE_UNINIT; 2531fe3f4442SDharageswari R } 2532fe3f4442SDharageswari R } 2533fe3f4442SDharageswari R 2534fe3f4442SDharageswari R void skl_cleanup_resources(struct skl *skl) 2535fe3f4442SDharageswari R { 2536fe3f4442SDharageswari R struct skl_sst *ctx = skl->skl_sst; 2537fe3f4442SDharageswari R struct snd_soc_platform *soc_platform = skl->platform; 2538fe3f4442SDharageswari R struct snd_soc_dapm_widget *w; 2539fe3f4442SDharageswari R struct snd_soc_card *card; 2540fe3f4442SDharageswari R 2541fe3f4442SDharageswari R if (soc_platform == NULL) 2542fe3f4442SDharageswari R return; 2543fe3f4442SDharageswari R 2544fe3f4442SDharageswari R card = soc_platform->component.card; 2545fe3f4442SDharageswari R if (!card || !card->instantiated) 2546fe3f4442SDharageswari R return; 2547fe3f4442SDharageswari R 2548fe3f4442SDharageswari R skl->resource.mem = 0; 2549fe3f4442SDharageswari R skl->resource.mcps = 0; 2550fe3f4442SDharageswari R 2551fe3f4442SDharageswari R list_for_each_entry(w, &card->widgets, list) { 2552fe3f4442SDharageswari R if (is_skl_dsp_widget_type(w) && (w->priv != NULL)) 2553fe3f4442SDharageswari R skl_clear_pin_config(soc_platform, w); 2554fe3f4442SDharageswari R } 2555fe3f4442SDharageswari R 2556fe3f4442SDharageswari R skl_clear_module_cnt(ctx->dsp); 2557fe3f4442SDharageswari R } 2558fe3f4442SDharageswari R 25593af36706SVinod Koul /* 25603af36706SVinod Koul * Topology core widget load callback 25613af36706SVinod Koul * 25623af36706SVinod Koul * This is used to save the private data for each widget which gives 25633af36706SVinod Koul * information to the driver about module and pipeline parameters which DSP 25643af36706SVinod Koul * FW expects like ids, resource values, formats etc 25653af36706SVinod Koul */ 25663af36706SVinod Koul static int skl_tplg_widget_load(struct snd_soc_component *cmpnt, 25673af36706SVinod Koul struct snd_soc_dapm_widget *w, 25683af36706SVinod Koul struct snd_soc_tplg_dapm_widget *tplg_w) 25693af36706SVinod Koul { 25703af36706SVinod Koul int ret; 25713af36706SVinod Koul struct hdac_ext_bus *ebus = snd_soc_component_get_drvdata(cmpnt); 25723af36706SVinod Koul struct skl *skl = ebus_to_skl(ebus); 25733af36706SVinod Koul struct hdac_bus *bus = ebus_to_hbus(ebus); 25743af36706SVinod Koul struct skl_module_cfg *mconfig; 25753af36706SVinod Koul 25763af36706SVinod Koul if (!tplg_w->priv.size) 25773af36706SVinod Koul goto bind_event; 25783af36706SVinod Koul 25793af36706SVinod Koul mconfig = devm_kzalloc(bus->dev, sizeof(*mconfig), GFP_KERNEL); 25803af36706SVinod Koul 25813af36706SVinod Koul if (!mconfig) 25823af36706SVinod Koul return -ENOMEM; 25833af36706SVinod Koul 25843af36706SVinod Koul w->priv = mconfig; 258509305da9SShreyas NC 2586b7c50555SVinod Koul /* 2587b7c50555SVinod Koul * module binary can be loaded later, so set it to query when 2588b7c50555SVinod Koul * module is load for a use case 2589b7c50555SVinod Koul */ 2590b7c50555SVinod Koul mconfig->id.module_id = -1; 25914cd9899fSHardik T Shah 25926277e832SShreyas NC /* Parse private data for tuples */ 25936277e832SShreyas NC ret = skl_tplg_get_pvt_data(tplg_w, skl, bus->dev, mconfig); 25946277e832SShreyas NC if (ret < 0) 25956277e832SShreyas NC return ret; 2596d14700a0SVinod Koul 2597d14700a0SVinod Koul skl_debug_init_module(skl->debugfs, w, mconfig); 2598d14700a0SVinod Koul 25993af36706SVinod Koul bind_event: 26003af36706SVinod Koul if (tplg_w->event_type == 0) { 26013373f716SVinod Koul dev_dbg(bus->dev, "ASoC: No event handler required\n"); 26023af36706SVinod Koul return 0; 26033af36706SVinod Koul } 26043af36706SVinod Koul 26053af36706SVinod Koul ret = snd_soc_tplg_widget_bind_event(w, skl_tplg_widget_ops, 2606b663a8c5SJeeja KP ARRAY_SIZE(skl_tplg_widget_ops), 2607b663a8c5SJeeja KP tplg_w->event_type); 26083af36706SVinod Koul 26093af36706SVinod Koul if (ret) { 26103af36706SVinod Koul dev_err(bus->dev, "%s: No matching event handlers found for %d\n", 26113af36706SVinod Koul __func__, tplg_w->event_type); 26123af36706SVinod Koul return -EINVAL; 26133af36706SVinod Koul } 26143af36706SVinod Koul 26153af36706SVinod Koul return 0; 26163af36706SVinod Koul } 26173af36706SVinod Koul 2618140adfbaSJeeja KP static int skl_init_algo_data(struct device *dev, struct soc_bytes_ext *be, 2619140adfbaSJeeja KP struct snd_soc_tplg_bytes_control *bc) 2620140adfbaSJeeja KP { 2621140adfbaSJeeja KP struct skl_algo_data *ac; 2622140adfbaSJeeja KP struct skl_dfw_algo_data *dfw_ac = 2623140adfbaSJeeja KP (struct skl_dfw_algo_data *)bc->priv.data; 2624140adfbaSJeeja KP 2625140adfbaSJeeja KP ac = devm_kzalloc(dev, sizeof(*ac), GFP_KERNEL); 2626140adfbaSJeeja KP if (!ac) 2627140adfbaSJeeja KP return -ENOMEM; 2628140adfbaSJeeja KP 2629140adfbaSJeeja KP /* Fill private data */ 2630140adfbaSJeeja KP ac->max = dfw_ac->max; 2631140adfbaSJeeja KP ac->param_id = dfw_ac->param_id; 2632140adfbaSJeeja KP ac->set_params = dfw_ac->set_params; 26330d682104SDharageswari R ac->size = dfw_ac->max; 2634140adfbaSJeeja KP 2635140adfbaSJeeja KP if (ac->max) { 2636140adfbaSJeeja KP ac->params = (char *) devm_kzalloc(dev, ac->max, GFP_KERNEL); 2637140adfbaSJeeja KP if (!ac->params) 2638140adfbaSJeeja KP return -ENOMEM; 2639140adfbaSJeeja KP 2640140adfbaSJeeja KP memcpy(ac->params, dfw_ac->params, ac->max); 2641140adfbaSJeeja KP } 2642140adfbaSJeeja KP 2643140adfbaSJeeja KP be->dobj.private = ac; 2644140adfbaSJeeja KP return 0; 2645140adfbaSJeeja KP } 2646140adfbaSJeeja KP 26477a1b749bSDharageswari R static int skl_init_enum_data(struct device *dev, struct soc_enum *se, 26487a1b749bSDharageswari R struct snd_soc_tplg_enum_control *ec) 26497a1b749bSDharageswari R { 26507a1b749bSDharageswari R 26517a1b749bSDharageswari R void *data; 26527a1b749bSDharageswari R 26537a1b749bSDharageswari R if (ec->priv.size) { 26547a1b749bSDharageswari R data = devm_kzalloc(dev, sizeof(ec->priv.size), GFP_KERNEL); 26557a1b749bSDharageswari R if (!data) 26567a1b749bSDharageswari R return -ENOMEM; 26577a1b749bSDharageswari R memcpy(data, ec->priv.data, ec->priv.size); 26587a1b749bSDharageswari R se->dobj.private = data; 26597a1b749bSDharageswari R } 26607a1b749bSDharageswari R 26617a1b749bSDharageswari R return 0; 26627a1b749bSDharageswari R 26637a1b749bSDharageswari R } 26647a1b749bSDharageswari R 2665140adfbaSJeeja KP static int skl_tplg_control_load(struct snd_soc_component *cmpnt, 2666140adfbaSJeeja KP struct snd_kcontrol_new *kctl, 2667140adfbaSJeeja KP struct snd_soc_tplg_ctl_hdr *hdr) 2668140adfbaSJeeja KP { 2669140adfbaSJeeja KP struct soc_bytes_ext *sb; 2670140adfbaSJeeja KP struct snd_soc_tplg_bytes_control *tplg_bc; 26717a1b749bSDharageswari R struct snd_soc_tplg_enum_control *tplg_ec; 2672140adfbaSJeeja KP struct hdac_ext_bus *ebus = snd_soc_component_get_drvdata(cmpnt); 2673140adfbaSJeeja KP struct hdac_bus *bus = ebus_to_hbus(ebus); 26747a1b749bSDharageswari R struct soc_enum *se; 2675140adfbaSJeeja KP 2676140adfbaSJeeja KP switch (hdr->ops.info) { 2677140adfbaSJeeja KP case SND_SOC_TPLG_CTL_BYTES: 2678140adfbaSJeeja KP tplg_bc = container_of(hdr, 2679140adfbaSJeeja KP struct snd_soc_tplg_bytes_control, hdr); 2680140adfbaSJeeja KP if (kctl->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { 2681140adfbaSJeeja KP sb = (struct soc_bytes_ext *)kctl->private_value; 2682140adfbaSJeeja KP if (tplg_bc->priv.size) 2683140adfbaSJeeja KP return skl_init_algo_data( 2684140adfbaSJeeja KP bus->dev, sb, tplg_bc); 2685140adfbaSJeeja KP } 2686140adfbaSJeeja KP break; 2687140adfbaSJeeja KP 26887a1b749bSDharageswari R case SND_SOC_TPLG_CTL_ENUM: 26897a1b749bSDharageswari R tplg_ec = container_of(hdr, 26907a1b749bSDharageswari R struct snd_soc_tplg_enum_control, hdr); 26917a1b749bSDharageswari R if (kctl->access & SNDRV_CTL_ELEM_ACCESS_READWRITE) { 26927a1b749bSDharageswari R se = (struct soc_enum *)kctl->private_value; 26937a1b749bSDharageswari R if (tplg_ec->priv.size) 26947a1b749bSDharageswari R return skl_init_enum_data(bus->dev, se, 26957a1b749bSDharageswari R tplg_ec); 26967a1b749bSDharageswari R } 26977a1b749bSDharageswari R break; 26987a1b749bSDharageswari R 2699140adfbaSJeeja KP default: 2700140adfbaSJeeja KP dev_warn(bus->dev, "Control load not supported %d:%d:%d\n", 2701140adfbaSJeeja KP hdr->ops.get, hdr->ops.put, hdr->ops.info); 2702140adfbaSJeeja KP break; 2703140adfbaSJeeja KP } 2704140adfbaSJeeja KP 2705140adfbaSJeeja KP return 0; 2706140adfbaSJeeja KP } 2707140adfbaSJeeja KP 2708541070ceSShreyas NC static int skl_tplg_fill_str_mfest_tkn(struct device *dev, 2709541070ceSShreyas NC struct snd_soc_tplg_vendor_string_elem *str_elem, 2710eee0e16fSJeeja KP struct skl *skl) 2711541070ceSShreyas NC { 2712541070ceSShreyas NC int tkn_count = 0; 2713541070ceSShreyas NC static int ref_count; 2714541070ceSShreyas NC 2715541070ceSShreyas NC switch (str_elem->token) { 2716541070ceSShreyas NC case SKL_TKN_STR_LIB_NAME: 2717eee0e16fSJeeja KP if (ref_count > skl->skl_sst->lib_count - 1) { 2718541070ceSShreyas NC ref_count = 0; 2719541070ceSShreyas NC return -EINVAL; 2720541070ceSShreyas NC } 2721541070ceSShreyas NC 2722eee0e16fSJeeja KP strncpy(skl->skl_sst->lib_info[ref_count].name, 2723eee0e16fSJeeja KP str_elem->string, 2724eee0e16fSJeeja KP ARRAY_SIZE(skl->skl_sst->lib_info[ref_count].name)); 2725541070ceSShreyas NC ref_count++; 2726541070ceSShreyas NC break; 2727541070ceSShreyas NC 2728541070ceSShreyas NC default: 2729ecd286a9SColin Ian King dev_err(dev, "Not a string token %d\n", str_elem->token); 2730541070ceSShreyas NC break; 2731541070ceSShreyas NC } 2732*db6ed55dSShreyas NC tkn_count++; 2733541070ceSShreyas NC 2734541070ceSShreyas NC return tkn_count; 2735541070ceSShreyas NC } 2736541070ceSShreyas NC 2737541070ceSShreyas NC static int skl_tplg_get_str_tkn(struct device *dev, 2738541070ceSShreyas NC struct snd_soc_tplg_vendor_array *array, 2739eee0e16fSJeeja KP struct skl *skl) 2740541070ceSShreyas NC { 2741541070ceSShreyas NC int tkn_count = 0, ret; 2742541070ceSShreyas NC struct snd_soc_tplg_vendor_string_elem *str_elem; 2743541070ceSShreyas NC 2744541070ceSShreyas NC str_elem = (struct snd_soc_tplg_vendor_string_elem *)array->value; 2745541070ceSShreyas NC while (tkn_count < array->num_elems) { 2746eee0e16fSJeeja KP ret = skl_tplg_fill_str_mfest_tkn(dev, str_elem, skl); 2747541070ceSShreyas NC str_elem++; 2748541070ceSShreyas NC 2749541070ceSShreyas NC if (ret < 0) 2750541070ceSShreyas NC return ret; 2751541070ceSShreyas NC 2752541070ceSShreyas NC tkn_count = tkn_count + ret; 2753541070ceSShreyas NC } 2754541070ceSShreyas NC 2755541070ceSShreyas NC return tkn_count; 2756541070ceSShreyas NC } 2757541070ceSShreyas NC 2758*db6ed55dSShreyas NC static int skl_tplg_manifest_fill_fmt(struct device *dev, 2759*db6ed55dSShreyas NC struct skl_module_iface *fmt, 2760*db6ed55dSShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem, 2761*db6ed55dSShreyas NC u32 dir, int fmt_idx) 2762*db6ed55dSShreyas NC { 2763*db6ed55dSShreyas NC struct skl_module_pin_fmt *dst_fmt; 2764*db6ed55dSShreyas NC struct skl_module_fmt *mod_fmt; 2765*db6ed55dSShreyas NC int ret; 2766*db6ed55dSShreyas NC 2767*db6ed55dSShreyas NC if (!fmt) 2768*db6ed55dSShreyas NC return -EINVAL; 2769*db6ed55dSShreyas NC 2770*db6ed55dSShreyas NC switch (dir) { 2771*db6ed55dSShreyas NC case SKL_DIR_IN: 2772*db6ed55dSShreyas NC dst_fmt = &fmt->inputs[fmt_idx]; 2773*db6ed55dSShreyas NC break; 2774*db6ed55dSShreyas NC 2775*db6ed55dSShreyas NC case SKL_DIR_OUT: 2776*db6ed55dSShreyas NC dst_fmt = &fmt->outputs[fmt_idx]; 2777*db6ed55dSShreyas NC break; 2778*db6ed55dSShreyas NC 2779*db6ed55dSShreyas NC default: 2780*db6ed55dSShreyas NC dev_err(dev, "Invalid direction: %d\n", dir); 2781*db6ed55dSShreyas NC return -EINVAL; 2782*db6ed55dSShreyas NC } 2783*db6ed55dSShreyas NC 2784*db6ed55dSShreyas NC mod_fmt = &dst_fmt->fmt; 2785*db6ed55dSShreyas NC 2786*db6ed55dSShreyas NC switch (tkn_elem->token) { 2787*db6ed55dSShreyas NC case SKL_TKN_MM_U32_INTF_PIN_ID: 2788*db6ed55dSShreyas NC dst_fmt->id = tkn_elem->value; 2789*db6ed55dSShreyas NC break; 2790*db6ed55dSShreyas NC 2791*db6ed55dSShreyas NC default: 2792*db6ed55dSShreyas NC ret = skl_tplg_fill_fmt(dev, mod_fmt, tkn_elem->token, 2793*db6ed55dSShreyas NC tkn_elem->value); 2794*db6ed55dSShreyas NC if (ret < 0) 2795*db6ed55dSShreyas NC return ret; 2796*db6ed55dSShreyas NC break; 2797*db6ed55dSShreyas NC } 2798*db6ed55dSShreyas NC 2799*db6ed55dSShreyas NC return 0; 2800*db6ed55dSShreyas NC } 2801*db6ed55dSShreyas NC 2802*db6ed55dSShreyas NC static int skl_tplg_fill_mod_info(struct device *dev, 2803*db6ed55dSShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem, 2804*db6ed55dSShreyas NC struct skl_module *mod) 2805*db6ed55dSShreyas NC { 2806*db6ed55dSShreyas NC 2807*db6ed55dSShreyas NC if (!mod) 2808*db6ed55dSShreyas NC return -EINVAL; 2809*db6ed55dSShreyas NC 2810*db6ed55dSShreyas NC switch (tkn_elem->token) { 2811*db6ed55dSShreyas NC case SKL_TKN_U8_IN_PIN_TYPE: 2812*db6ed55dSShreyas NC mod->input_pin_type = tkn_elem->value; 2813*db6ed55dSShreyas NC break; 2814*db6ed55dSShreyas NC 2815*db6ed55dSShreyas NC case SKL_TKN_U8_OUT_PIN_TYPE: 2816*db6ed55dSShreyas NC mod->output_pin_type = tkn_elem->value; 2817*db6ed55dSShreyas NC break; 2818*db6ed55dSShreyas NC 2819*db6ed55dSShreyas NC case SKL_TKN_U8_IN_QUEUE_COUNT: 2820*db6ed55dSShreyas NC mod->max_input_pins = tkn_elem->value; 2821*db6ed55dSShreyas NC break; 2822*db6ed55dSShreyas NC 2823*db6ed55dSShreyas NC case SKL_TKN_U8_OUT_QUEUE_COUNT: 2824*db6ed55dSShreyas NC mod->max_output_pins = tkn_elem->value; 2825*db6ed55dSShreyas NC break; 2826*db6ed55dSShreyas NC 2827*db6ed55dSShreyas NC case SKL_TKN_MM_U8_NUM_RES: 2828*db6ed55dSShreyas NC mod->nr_resources = tkn_elem->value; 2829*db6ed55dSShreyas NC break; 2830*db6ed55dSShreyas NC 2831*db6ed55dSShreyas NC case SKL_TKN_MM_U8_NUM_INTF: 2832*db6ed55dSShreyas NC mod->nr_interfaces = tkn_elem->value; 2833*db6ed55dSShreyas NC break; 2834*db6ed55dSShreyas NC 2835*db6ed55dSShreyas NC default: 2836*db6ed55dSShreyas NC dev_err(dev, "Invalid mod info token %d", tkn_elem->token); 2837*db6ed55dSShreyas NC return -EINVAL; 2838*db6ed55dSShreyas NC } 2839*db6ed55dSShreyas NC 2840*db6ed55dSShreyas NC return 0; 2841*db6ed55dSShreyas NC } 2842*db6ed55dSShreyas NC 2843*db6ed55dSShreyas NC 2844541070ceSShreyas NC static int skl_tplg_get_int_tkn(struct device *dev, 2845541070ceSShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem, 2846eee0e16fSJeeja KP struct skl *skl) 2847541070ceSShreyas NC { 2848*db6ed55dSShreyas NC int tkn_count = 0, ret; 2849*db6ed55dSShreyas NC static int mod_idx, res_val_idx, intf_val_idx, dir, pin_idx; 2850*db6ed55dSShreyas NC struct skl_module_res *res = NULL; 2851*db6ed55dSShreyas NC struct skl_module_iface *fmt = NULL; 2852*db6ed55dSShreyas NC struct skl_module *mod = NULL; 2853*db6ed55dSShreyas NC int i; 2854*db6ed55dSShreyas NC 2855*db6ed55dSShreyas NC if (skl->modules) { 2856*db6ed55dSShreyas NC mod = skl->modules[mod_idx]; 2857*db6ed55dSShreyas NC res = &mod->resources[res_val_idx]; 2858*db6ed55dSShreyas NC fmt = &mod->formats[intf_val_idx]; 2859*db6ed55dSShreyas NC } 2860541070ceSShreyas NC 2861541070ceSShreyas NC switch (tkn_elem->token) { 2862541070ceSShreyas NC case SKL_TKN_U32_LIB_COUNT: 2863eee0e16fSJeeja KP skl->skl_sst->lib_count = tkn_elem->value; 2864*db6ed55dSShreyas NC break; 2865*db6ed55dSShreyas NC 2866*db6ed55dSShreyas NC case SKL_TKN_U8_NUM_MOD: 2867*db6ed55dSShreyas NC skl->nr_modules = tkn_elem->value; 2868*db6ed55dSShreyas NC skl->modules = devm_kcalloc(dev, skl->nr_modules, 2869*db6ed55dSShreyas NC sizeof(*skl->modules), GFP_KERNEL); 2870*db6ed55dSShreyas NC if (!skl->modules) 2871*db6ed55dSShreyas NC return -ENOMEM; 2872*db6ed55dSShreyas NC 2873*db6ed55dSShreyas NC for (i = 0; i < skl->nr_modules; i++) { 2874*db6ed55dSShreyas NC skl->modules[i] = devm_kzalloc(dev, 2875*db6ed55dSShreyas NC sizeof(struct skl_module), GFP_KERNEL); 2876*db6ed55dSShreyas NC if (!skl->modules[i]) 2877*db6ed55dSShreyas NC return -ENOMEM; 2878*db6ed55dSShreyas NC } 2879*db6ed55dSShreyas NC break; 2880*db6ed55dSShreyas NC 2881*db6ed55dSShreyas NC case SKL_TKN_MM_U8_MOD_IDX: 2882*db6ed55dSShreyas NC mod_idx = tkn_elem->value; 2883*db6ed55dSShreyas NC break; 2884*db6ed55dSShreyas NC 2885*db6ed55dSShreyas NC case SKL_TKN_U8_IN_PIN_TYPE: 2886*db6ed55dSShreyas NC case SKL_TKN_U8_OUT_PIN_TYPE: 2887*db6ed55dSShreyas NC case SKL_TKN_U8_IN_QUEUE_COUNT: 2888*db6ed55dSShreyas NC case SKL_TKN_U8_OUT_QUEUE_COUNT: 2889*db6ed55dSShreyas NC case SKL_TKN_MM_U8_NUM_RES: 2890*db6ed55dSShreyas NC case SKL_TKN_MM_U8_NUM_INTF: 2891*db6ed55dSShreyas NC ret = skl_tplg_fill_mod_info(dev, tkn_elem, mod); 2892*db6ed55dSShreyas NC if (ret < 0) 2893*db6ed55dSShreyas NC return ret; 2894*db6ed55dSShreyas NC break; 2895*db6ed55dSShreyas NC 2896*db6ed55dSShreyas NC case SKL_TKN_U32_DIR_PIN_COUNT: 2897*db6ed55dSShreyas NC dir = tkn_elem->value & SKL_IN_DIR_BIT_MASK; 2898*db6ed55dSShreyas NC pin_idx = (tkn_elem->value & SKL_PIN_COUNT_MASK) >> 4; 2899*db6ed55dSShreyas NC break; 2900*db6ed55dSShreyas NC 2901*db6ed55dSShreyas NC case SKL_TKN_MM_U32_RES_ID: 2902*db6ed55dSShreyas NC if (!res) 2903*db6ed55dSShreyas NC return -EINVAL; 2904*db6ed55dSShreyas NC 2905*db6ed55dSShreyas NC res->id = tkn_elem->value; 2906*db6ed55dSShreyas NC res_val_idx = tkn_elem->value; 2907*db6ed55dSShreyas NC break; 2908*db6ed55dSShreyas NC 2909*db6ed55dSShreyas NC case SKL_TKN_MM_U32_FMT_ID: 2910*db6ed55dSShreyas NC if (!fmt) 2911*db6ed55dSShreyas NC return -EINVAL; 2912*db6ed55dSShreyas NC 2913*db6ed55dSShreyas NC fmt->fmt_idx = tkn_elem->value; 2914*db6ed55dSShreyas NC intf_val_idx = tkn_elem->value; 2915*db6ed55dSShreyas NC break; 2916*db6ed55dSShreyas NC 2917*db6ed55dSShreyas NC case SKL_TKN_MM_U32_CPS: 2918*db6ed55dSShreyas NC case SKL_TKN_MM_U32_DMA_SIZE: 2919*db6ed55dSShreyas NC case SKL_TKN_MM_U32_CPC: 2920*db6ed55dSShreyas NC case SKL_TKN_U32_MEM_PAGES: 2921*db6ed55dSShreyas NC case SKL_TKN_U32_OBS: 2922*db6ed55dSShreyas NC case SKL_TKN_U32_IBS: 2923*db6ed55dSShreyas NC case SKL_TKN_MM_U32_RES_PIN_ID: 2924*db6ed55dSShreyas NC case SKL_TKN_MM_U32_PIN_BUF: 2925*db6ed55dSShreyas NC ret = skl_tplg_fill_res_tkn(dev, tkn_elem, res, pin_idx, dir); 2926*db6ed55dSShreyas NC if (ret < 0) 2927*db6ed55dSShreyas NC return ret; 2928*db6ed55dSShreyas NC 2929*db6ed55dSShreyas NC break; 2930*db6ed55dSShreyas NC 2931*db6ed55dSShreyas NC case SKL_TKN_MM_U32_NUM_IN_FMT: 2932*db6ed55dSShreyas NC if (!fmt) 2933*db6ed55dSShreyas NC return -EINVAL; 2934*db6ed55dSShreyas NC 2935*db6ed55dSShreyas NC res->nr_input_pins = tkn_elem->value; 2936*db6ed55dSShreyas NC break; 2937*db6ed55dSShreyas NC 2938*db6ed55dSShreyas NC case SKL_TKN_MM_U32_NUM_OUT_FMT: 2939*db6ed55dSShreyas NC if (!fmt) 2940*db6ed55dSShreyas NC return -EINVAL; 2941*db6ed55dSShreyas NC 2942*db6ed55dSShreyas NC res->nr_output_pins = tkn_elem->value; 2943*db6ed55dSShreyas NC break; 2944*db6ed55dSShreyas NC 2945*db6ed55dSShreyas NC case SKL_TKN_U32_FMT_CH: 2946*db6ed55dSShreyas NC case SKL_TKN_U32_FMT_FREQ: 2947*db6ed55dSShreyas NC case SKL_TKN_U32_FMT_BIT_DEPTH: 2948*db6ed55dSShreyas NC case SKL_TKN_U32_FMT_SAMPLE_SIZE: 2949*db6ed55dSShreyas NC case SKL_TKN_U32_FMT_CH_CONFIG: 2950*db6ed55dSShreyas NC case SKL_TKN_U32_FMT_INTERLEAVE: 2951*db6ed55dSShreyas NC case SKL_TKN_U32_FMT_SAMPLE_TYPE: 2952*db6ed55dSShreyas NC case SKL_TKN_U32_FMT_CH_MAP: 2953*db6ed55dSShreyas NC case SKL_TKN_MM_U32_INTF_PIN_ID: 2954*db6ed55dSShreyas NC ret = skl_tplg_manifest_fill_fmt(dev, fmt, tkn_elem, 2955*db6ed55dSShreyas NC dir, pin_idx); 2956*db6ed55dSShreyas NC if (ret < 0) 2957*db6ed55dSShreyas NC return ret; 2958541070ceSShreyas NC break; 2959541070ceSShreyas NC 2960541070ceSShreyas NC default: 2961ecd286a9SColin Ian King dev_err(dev, "Not a manifest token %d\n", tkn_elem->token); 2962541070ceSShreyas NC return -EINVAL; 2963541070ceSShreyas NC } 2964*db6ed55dSShreyas NC tkn_count++; 2965541070ceSShreyas NC 2966541070ceSShreyas NC return tkn_count; 2967541070ceSShreyas NC } 2968541070ceSShreyas NC 2969*db6ed55dSShreyas NC static int skl_tplg_get_manifest_uuid(struct device *dev, 2970*db6ed55dSShreyas NC struct skl *skl, 2971*db6ed55dSShreyas NC struct snd_soc_tplg_vendor_uuid_elem *uuid_tkn) 2972*db6ed55dSShreyas NC { 2973*db6ed55dSShreyas NC static int ref_count; 2974*db6ed55dSShreyas NC struct skl_module *mod; 2975*db6ed55dSShreyas NC 2976*db6ed55dSShreyas NC if (uuid_tkn->token == SKL_TKN_UUID) { 2977*db6ed55dSShreyas NC mod = skl->modules[ref_count]; 2978*db6ed55dSShreyas NC memcpy(&mod->uuid, &uuid_tkn->uuid, sizeof(uuid_tkn->uuid)); 2979*db6ed55dSShreyas NC ref_count++; 2980*db6ed55dSShreyas NC } else { 2981*db6ed55dSShreyas NC dev_err(dev, "Not an UUID token tkn %d\n", uuid_tkn->token); 2982*db6ed55dSShreyas NC return -EINVAL; 2983*db6ed55dSShreyas NC } 2984*db6ed55dSShreyas NC 2985*db6ed55dSShreyas NC return 0; 2986*db6ed55dSShreyas NC } 2987*db6ed55dSShreyas NC 2988541070ceSShreyas NC /* 2989541070ceSShreyas NC * Fill the manifest structure by parsing the tokens based on the 2990541070ceSShreyas NC * type. 2991541070ceSShreyas NC */ 2992541070ceSShreyas NC static int skl_tplg_get_manifest_tkn(struct device *dev, 2993eee0e16fSJeeja KP char *pvt_data, struct skl *skl, 2994541070ceSShreyas NC int block_size) 2995541070ceSShreyas NC { 2996541070ceSShreyas NC int tkn_count = 0, ret; 2997541070ceSShreyas NC int off = 0, tuple_size = 0; 2998541070ceSShreyas NC struct snd_soc_tplg_vendor_array *array; 2999541070ceSShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem; 3000541070ceSShreyas NC 3001541070ceSShreyas NC if (block_size <= 0) 3002541070ceSShreyas NC return -EINVAL; 3003541070ceSShreyas NC 3004541070ceSShreyas NC while (tuple_size < block_size) { 3005541070ceSShreyas NC array = (struct snd_soc_tplg_vendor_array *)(pvt_data + off); 3006541070ceSShreyas NC off += array->size; 3007541070ceSShreyas NC switch (array->type) { 3008541070ceSShreyas NC case SND_SOC_TPLG_TUPLE_TYPE_STRING: 3009eee0e16fSJeeja KP ret = skl_tplg_get_str_tkn(dev, array, skl); 3010541070ceSShreyas NC 3011541070ceSShreyas NC if (ret < 0) 3012541070ceSShreyas NC return ret; 30130a716776SShreyas NC tkn_count = ret; 3014541070ceSShreyas NC 3015541070ceSShreyas NC tuple_size += tkn_count * 3016541070ceSShreyas NC sizeof(struct snd_soc_tplg_vendor_string_elem); 3017541070ceSShreyas NC continue; 3018541070ceSShreyas NC 3019541070ceSShreyas NC case SND_SOC_TPLG_TUPLE_TYPE_UUID: 3020*db6ed55dSShreyas NC ret = skl_tplg_get_manifest_uuid(dev, skl, array->uuid); 3021*db6ed55dSShreyas NC if (ret < 0) 3022*db6ed55dSShreyas NC return ret; 3023*db6ed55dSShreyas NC 3024*db6ed55dSShreyas NC tuple_size += sizeof(*array->uuid); 3025541070ceSShreyas NC continue; 3026541070ceSShreyas NC 3027541070ceSShreyas NC default: 3028541070ceSShreyas NC tkn_elem = array->value; 3029541070ceSShreyas NC tkn_count = 0; 3030541070ceSShreyas NC break; 3031541070ceSShreyas NC } 3032541070ceSShreyas NC 3033541070ceSShreyas NC while (tkn_count <= array->num_elems - 1) { 3034541070ceSShreyas NC ret = skl_tplg_get_int_tkn(dev, 3035eee0e16fSJeeja KP tkn_elem, skl); 3036541070ceSShreyas NC if (ret < 0) 3037541070ceSShreyas NC return ret; 3038541070ceSShreyas NC 3039541070ceSShreyas NC tkn_count = tkn_count + ret; 3040541070ceSShreyas NC tkn_elem++; 3041541070ceSShreyas NC } 30429fc129f6SShreyas NC tuple_size += (tkn_count * sizeof(*tkn_elem)); 3043541070ceSShreyas NC tkn_count = 0; 3044541070ceSShreyas NC } 3045541070ceSShreyas NC 30469fc129f6SShreyas NC return off; 3047541070ceSShreyas NC } 3048541070ceSShreyas NC 3049541070ceSShreyas NC /* 3050541070ceSShreyas NC * Parse manifest private data for tokens. The private data block is 3051541070ceSShreyas NC * preceded by descriptors for type and size of data block. 3052541070ceSShreyas NC */ 3053541070ceSShreyas NC static int skl_tplg_get_manifest_data(struct snd_soc_tplg_manifest *manifest, 3054eee0e16fSJeeja KP struct device *dev, struct skl *skl) 3055541070ceSShreyas NC { 3056541070ceSShreyas NC struct snd_soc_tplg_vendor_array *array; 3057541070ceSShreyas NC int num_blocks, block_size = 0, block_type, off = 0; 3058541070ceSShreyas NC char *data; 3059541070ceSShreyas NC int ret; 3060541070ceSShreyas NC 3061541070ceSShreyas NC /* Read the NUM_DATA_BLOCKS descriptor */ 3062541070ceSShreyas NC array = (struct snd_soc_tplg_vendor_array *)manifest->priv.data; 3063541070ceSShreyas NC ret = skl_tplg_get_desc_blocks(dev, array); 3064541070ceSShreyas NC if (ret < 0) 3065541070ceSShreyas NC return ret; 3066541070ceSShreyas NC num_blocks = ret; 3067541070ceSShreyas NC 3068541070ceSShreyas NC off += array->size; 3069541070ceSShreyas NC /* Read the BLOCK_TYPE and BLOCK_SIZE descriptor */ 3070541070ceSShreyas NC while (num_blocks > 0) { 30719fc129f6SShreyas NC array = (struct snd_soc_tplg_vendor_array *) 30729fc129f6SShreyas NC (manifest->priv.data + off); 3073541070ceSShreyas NC ret = skl_tplg_get_desc_blocks(dev, array); 3074541070ceSShreyas NC 3075541070ceSShreyas NC if (ret < 0) 3076541070ceSShreyas NC return ret; 3077541070ceSShreyas NC block_type = ret; 3078541070ceSShreyas NC off += array->size; 3079541070ceSShreyas NC 3080541070ceSShreyas NC array = (struct snd_soc_tplg_vendor_array *) 3081541070ceSShreyas NC (manifest->priv.data + off); 3082541070ceSShreyas NC 3083541070ceSShreyas NC ret = skl_tplg_get_desc_blocks(dev, array); 3084541070ceSShreyas NC 3085541070ceSShreyas NC if (ret < 0) 3086541070ceSShreyas NC return ret; 3087541070ceSShreyas NC block_size = ret; 3088541070ceSShreyas NC off += array->size; 3089541070ceSShreyas NC 3090541070ceSShreyas NC array = (struct snd_soc_tplg_vendor_array *) 3091541070ceSShreyas NC (manifest->priv.data + off); 3092541070ceSShreyas NC 3093541070ceSShreyas NC data = (manifest->priv.data + off); 3094541070ceSShreyas NC 3095541070ceSShreyas NC if (block_type == SKL_TYPE_TUPLE) { 3096eee0e16fSJeeja KP ret = skl_tplg_get_manifest_tkn(dev, data, skl, 3097541070ceSShreyas NC block_size); 3098541070ceSShreyas NC 3099541070ceSShreyas NC if (ret < 0) 3100541070ceSShreyas NC return ret; 3101541070ceSShreyas NC 3102541070ceSShreyas NC --num_blocks; 3103541070ceSShreyas NC } else { 3104541070ceSShreyas NC return -EINVAL; 3105541070ceSShreyas NC } 31069fc129f6SShreyas NC off += ret; 3107541070ceSShreyas NC } 3108541070ceSShreyas NC 3109541070ceSShreyas NC return 0; 3110541070ceSShreyas NC } 3111541070ceSShreyas NC 311215ecaba9SKranthi G static int skl_manifest_load(struct snd_soc_component *cmpnt, 311315ecaba9SKranthi G struct snd_soc_tplg_manifest *manifest) 311415ecaba9SKranthi G { 311515ecaba9SKranthi G struct hdac_ext_bus *ebus = snd_soc_component_get_drvdata(cmpnt); 311615ecaba9SKranthi G struct hdac_bus *bus = ebus_to_hbus(ebus); 311715ecaba9SKranthi G struct skl *skl = ebus_to_skl(ebus); 311815ecaba9SKranthi G 3119c15ad605SVinod Koul /* proceed only if we have private data defined */ 3120c15ad605SVinod Koul if (manifest->priv.size == 0) 3121c15ad605SVinod Koul return 0; 3122c15ad605SVinod Koul 3123eee0e16fSJeeja KP skl_tplg_get_manifest_data(manifest, bus->dev, skl); 3124541070ceSShreyas NC 3125eee0e16fSJeeja KP if (skl->skl_sst->lib_count > SKL_MAX_LIB) { 312615ecaba9SKranthi G dev_err(bus->dev, "Exceeding max Library count. Got:%d\n", 3127eee0e16fSJeeja KP skl->skl_sst->lib_count); 3128eee0e16fSJeeja KP return -EINVAL; 312915ecaba9SKranthi G } 313015ecaba9SKranthi G 3131eee0e16fSJeeja KP return 0; 313215ecaba9SKranthi G } 313315ecaba9SKranthi G 31343af36706SVinod Koul static struct snd_soc_tplg_ops skl_tplg_ops = { 31353af36706SVinod Koul .widget_load = skl_tplg_widget_load, 3136140adfbaSJeeja KP .control_load = skl_tplg_control_load, 3137140adfbaSJeeja KP .bytes_ext_ops = skl_tlv_ops, 3138140adfbaSJeeja KP .bytes_ext_ops_count = ARRAY_SIZE(skl_tlv_ops), 31397a1b749bSDharageswari R .io_ops = skl_tplg_kcontrol_ops, 31407a1b749bSDharageswari R .io_ops_count = ARRAY_SIZE(skl_tplg_kcontrol_ops), 314115ecaba9SKranthi G .manifest = skl_manifest_load, 31423af36706SVinod Koul }; 31433af36706SVinod Koul 3144287af4f9SJeeja KP /* 3145287af4f9SJeeja KP * A pipe can have multiple modules, each of them will be a DAPM widget as 3146287af4f9SJeeja KP * well. While managing a pipeline we need to get the list of all the 3147287af4f9SJeeja KP * widgets in a pipelines, so this helper - skl_tplg_create_pipe_widget_list() 3148287af4f9SJeeja KP * helps to get the SKL type widgets in that pipeline 3149287af4f9SJeeja KP */ 3150287af4f9SJeeja KP static int skl_tplg_create_pipe_widget_list(struct snd_soc_platform *platform) 3151287af4f9SJeeja KP { 3152287af4f9SJeeja KP struct snd_soc_dapm_widget *w; 3153287af4f9SJeeja KP struct skl_module_cfg *mcfg = NULL; 3154287af4f9SJeeja KP struct skl_pipe_module *p_module = NULL; 3155287af4f9SJeeja KP struct skl_pipe *pipe; 3156287af4f9SJeeja KP 3157287af4f9SJeeja KP list_for_each_entry(w, &platform->component.card->widgets, list) { 3158287af4f9SJeeja KP if (is_skl_dsp_widget_type(w) && w->priv != NULL) { 3159287af4f9SJeeja KP mcfg = w->priv; 3160287af4f9SJeeja KP pipe = mcfg->pipe; 3161287af4f9SJeeja KP 3162287af4f9SJeeja KP p_module = devm_kzalloc(platform->dev, 3163287af4f9SJeeja KP sizeof(*p_module), GFP_KERNEL); 3164287af4f9SJeeja KP if (!p_module) 3165287af4f9SJeeja KP return -ENOMEM; 3166287af4f9SJeeja KP 3167287af4f9SJeeja KP p_module->w = w; 3168287af4f9SJeeja KP list_add_tail(&p_module->node, &pipe->w_list); 3169287af4f9SJeeja KP } 3170287af4f9SJeeja KP } 3171287af4f9SJeeja KP 3172287af4f9SJeeja KP return 0; 3173287af4f9SJeeja KP } 3174287af4f9SJeeja KP 3175f0aa94faSJeeja KP static void skl_tplg_set_pipe_type(struct skl *skl, struct skl_pipe *pipe) 3176f0aa94faSJeeja KP { 3177f0aa94faSJeeja KP struct skl_pipe_module *w_module; 3178f0aa94faSJeeja KP struct snd_soc_dapm_widget *w; 3179f0aa94faSJeeja KP struct skl_module_cfg *mconfig; 3180f0aa94faSJeeja KP bool host_found = false, link_found = false; 3181f0aa94faSJeeja KP 3182f0aa94faSJeeja KP list_for_each_entry(w_module, &pipe->w_list, node) { 3183f0aa94faSJeeja KP w = w_module->w; 3184f0aa94faSJeeja KP mconfig = w->priv; 3185f0aa94faSJeeja KP 3186f0aa94faSJeeja KP if (mconfig->dev_type == SKL_DEVICE_HDAHOST) 3187f0aa94faSJeeja KP host_found = true; 3188f0aa94faSJeeja KP else if (mconfig->dev_type != SKL_DEVICE_NONE) 3189f0aa94faSJeeja KP link_found = true; 3190f0aa94faSJeeja KP } 3191f0aa94faSJeeja KP 3192f0aa94faSJeeja KP if (host_found && link_found) 3193f0aa94faSJeeja KP pipe->passthru = true; 3194f0aa94faSJeeja KP else 3195f0aa94faSJeeja KP pipe->passthru = false; 3196f0aa94faSJeeja KP } 3197f0aa94faSJeeja KP 31983af36706SVinod Koul /* This will be read from topology manifest, currently defined here */ 31993af36706SVinod Koul #define SKL_MAX_MCPS 30000000 32003af36706SVinod Koul #define SKL_FW_MAX_MEM 1000000 32013af36706SVinod Koul 32023af36706SVinod Koul /* 32033af36706SVinod Koul * SKL topology init routine 32043af36706SVinod Koul */ 32053af36706SVinod Koul int skl_tplg_init(struct snd_soc_platform *platform, struct hdac_ext_bus *ebus) 32063af36706SVinod Koul { 32073af36706SVinod Koul int ret; 32083af36706SVinod Koul const struct firmware *fw; 32093af36706SVinod Koul struct hdac_bus *bus = ebus_to_hbus(ebus); 32103af36706SVinod Koul struct skl *skl = ebus_to_skl(ebus); 3211f0aa94faSJeeja KP struct skl_pipeline *ppl; 32123af36706SVinod Koul 32134b235c43SVinod Koul ret = request_firmware(&fw, skl->tplg_name, bus->dev); 32143af36706SVinod Koul if (ret < 0) { 3215b663a8c5SJeeja KP dev_err(bus->dev, "tplg fw %s load failed with %d\n", 32164b235c43SVinod Koul skl->tplg_name, ret); 32174b235c43SVinod Koul ret = request_firmware(&fw, "dfw_sst.bin", bus->dev); 32184b235c43SVinod Koul if (ret < 0) { 32194b235c43SVinod Koul dev_err(bus->dev, "Fallback tplg fw %s load failed with %d\n", 32203af36706SVinod Koul "dfw_sst.bin", ret); 32213af36706SVinod Koul return ret; 32223af36706SVinod Koul } 32234b235c43SVinod Koul } 32243af36706SVinod Koul 32253af36706SVinod Koul /* 32263af36706SVinod Koul * The complete tplg for SKL is loaded as index 0, we don't use 32273af36706SVinod Koul * any other index 32283af36706SVinod Koul */ 3229b663a8c5SJeeja KP ret = snd_soc_tplg_component_load(&platform->component, 3230b663a8c5SJeeja KP &skl_tplg_ops, fw, 0); 32313af36706SVinod Koul if (ret < 0) { 32323af36706SVinod Koul dev_err(bus->dev, "tplg component load failed%d\n", ret); 3233c14a82c7SSudip Mukherjee release_firmware(fw); 32343af36706SVinod Koul return -EINVAL; 32353af36706SVinod Koul } 32363af36706SVinod Koul 32373af36706SVinod Koul skl->resource.max_mcps = SKL_MAX_MCPS; 32383af36706SVinod Koul skl->resource.max_mem = SKL_FW_MAX_MEM; 32393af36706SVinod Koul 3240d8018361SVinod Koul skl->tplg = fw; 3241287af4f9SJeeja KP ret = skl_tplg_create_pipe_widget_list(platform); 3242287af4f9SJeeja KP if (ret < 0) 3243287af4f9SJeeja KP return ret; 3244d8018361SVinod Koul 3245f0aa94faSJeeja KP list_for_each_entry(ppl, &skl->ppl_list, node) 3246f0aa94faSJeeja KP skl_tplg_set_pipe_type(skl, ppl->pipe); 32473af36706SVinod Koul 32483af36706SVinod Koul return 0; 3249e4e2d2f4SJeeja KP } 3250