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 52f6fa56e2SRamesh Babu #define CHECK_HW_PARAMS(ch, freq, bps, prm_ch, prm_freq, prm_bps) \ 53f6fa56e2SRamesh Babu ((ch == prm_ch) && (bps == prm_bps) && (freq == prm_freq)) 54f6fa56e2SRamesh Babu 55a83e3b4cSVinod Koul void skl_tplg_d0i3_get(struct skl *skl, enum d0i3_capability caps) 56a83e3b4cSVinod Koul { 57a83e3b4cSVinod Koul struct skl_d0i3_data *d0i3 = &skl->skl_sst->d0i3; 58a83e3b4cSVinod Koul 59a83e3b4cSVinod Koul switch (caps) { 60a83e3b4cSVinod Koul case SKL_D0I3_NONE: 61a83e3b4cSVinod Koul d0i3->non_d0i3++; 62a83e3b4cSVinod Koul break; 63a83e3b4cSVinod Koul 64a83e3b4cSVinod Koul case SKL_D0I3_STREAMING: 65a83e3b4cSVinod Koul d0i3->streaming++; 66a83e3b4cSVinod Koul break; 67a83e3b4cSVinod Koul 68a83e3b4cSVinod Koul case SKL_D0I3_NON_STREAMING: 69a83e3b4cSVinod Koul d0i3->non_streaming++; 70a83e3b4cSVinod Koul break; 71a83e3b4cSVinod Koul } 72a83e3b4cSVinod Koul } 73a83e3b4cSVinod Koul 74a83e3b4cSVinod Koul void skl_tplg_d0i3_put(struct skl *skl, enum d0i3_capability caps) 75a83e3b4cSVinod Koul { 76a83e3b4cSVinod Koul struct skl_d0i3_data *d0i3 = &skl->skl_sst->d0i3; 77a83e3b4cSVinod Koul 78a83e3b4cSVinod Koul switch (caps) { 79a83e3b4cSVinod Koul case SKL_D0I3_NONE: 80a83e3b4cSVinod Koul d0i3->non_d0i3--; 81a83e3b4cSVinod Koul break; 82a83e3b4cSVinod Koul 83a83e3b4cSVinod Koul case SKL_D0I3_STREAMING: 84a83e3b4cSVinod Koul d0i3->streaming--; 85a83e3b4cSVinod Koul break; 86a83e3b4cSVinod Koul 87a83e3b4cSVinod Koul case SKL_D0I3_NON_STREAMING: 88a83e3b4cSVinod Koul d0i3->non_streaming--; 89a83e3b4cSVinod Koul break; 90a83e3b4cSVinod Koul } 91a83e3b4cSVinod Koul } 92a83e3b4cSVinod Koul 93e4e2d2f4SJeeja KP /* 94e4e2d2f4SJeeja KP * SKL DSP driver modelling uses only few DAPM widgets so for rest we will 95e4e2d2f4SJeeja KP * ignore. This helpers checks if the SKL driver handles this widget type 96e4e2d2f4SJeeja KP */ 97e4e2d2f4SJeeja KP static int is_skl_dsp_widget_type(struct snd_soc_dapm_widget *w) 98e4e2d2f4SJeeja KP { 99e4e2d2f4SJeeja KP switch (w->id) { 100e4e2d2f4SJeeja KP case snd_soc_dapm_dai_link: 101e4e2d2f4SJeeja KP case snd_soc_dapm_dai_in: 102e4e2d2f4SJeeja KP case snd_soc_dapm_aif_in: 103e4e2d2f4SJeeja KP case snd_soc_dapm_aif_out: 104e4e2d2f4SJeeja KP case snd_soc_dapm_dai_out: 105e4e2d2f4SJeeja KP case snd_soc_dapm_switch: 106e4e2d2f4SJeeja KP return false; 107e4e2d2f4SJeeja KP default: 108e4e2d2f4SJeeja KP return true; 109e4e2d2f4SJeeja KP } 110e4e2d2f4SJeeja KP } 111e4e2d2f4SJeeja KP 112e4e2d2f4SJeeja KP /* 113e4e2d2f4SJeeja KP * Each pipelines needs memory to be allocated. Check if we have free memory 1149ba8ffefSDharageswari.R * from available pool. 115e4e2d2f4SJeeja KP */ 1169ba8ffefSDharageswari.R static bool skl_is_pipe_mem_avail(struct skl *skl, 117e4e2d2f4SJeeja KP struct skl_module_cfg *mconfig) 118e4e2d2f4SJeeja KP { 119e4e2d2f4SJeeja KP struct skl_sst *ctx = skl->skl_sst; 120e4e2d2f4SJeeja KP 121e4e2d2f4SJeeja KP if (skl->resource.mem + mconfig->pipe->memory_pages > 122e4e2d2f4SJeeja KP skl->resource.max_mem) { 123e4e2d2f4SJeeja KP dev_err(ctx->dev, 124e4e2d2f4SJeeja KP "%s: module_id %d instance %d\n", __func__, 125e4e2d2f4SJeeja KP mconfig->id.module_id, 126e4e2d2f4SJeeja KP mconfig->id.instance_id); 127e4e2d2f4SJeeja KP dev_err(ctx->dev, 128e4e2d2f4SJeeja KP "exceeds ppl memory available %d mem %d\n", 129e4e2d2f4SJeeja KP skl->resource.max_mem, skl->resource.mem); 130e4e2d2f4SJeeja KP return false; 1319ba8ffefSDharageswari.R } else { 1329ba8ffefSDharageswari.R return true; 1339ba8ffefSDharageswari.R } 134e4e2d2f4SJeeja KP } 135e4e2d2f4SJeeja KP 1369ba8ffefSDharageswari.R /* 1379ba8ffefSDharageswari.R * Add the mem to the mem pool. This is freed when pipe is deleted. 1389ba8ffefSDharageswari.R * Note: DSP does actual memory management we only keep track for complete 1399ba8ffefSDharageswari.R * pool 1409ba8ffefSDharageswari.R */ 1419ba8ffefSDharageswari.R static void skl_tplg_alloc_pipe_mem(struct skl *skl, 1429ba8ffefSDharageswari.R struct skl_module_cfg *mconfig) 1439ba8ffefSDharageswari.R { 144e4e2d2f4SJeeja KP skl->resource.mem += mconfig->pipe->memory_pages; 145e4e2d2f4SJeeja KP } 146e4e2d2f4SJeeja KP 147e4e2d2f4SJeeja KP /* 148e4e2d2f4SJeeja KP * Pipeline needs needs DSP CPU resources for computation, this is 149e4e2d2f4SJeeja KP * quantified in MCPS (Million Clocks Per Second) required for module/pipe 150e4e2d2f4SJeeja KP * 151e4e2d2f4SJeeja KP * Each pipelines needs mcps to be allocated. Check if we have mcps for this 1529ba8ffefSDharageswari.R * pipe. 153e4e2d2f4SJeeja KP */ 1549ba8ffefSDharageswari.R 1559ba8ffefSDharageswari.R static bool skl_is_pipe_mcps_avail(struct skl *skl, 156e4e2d2f4SJeeja KP struct skl_module_cfg *mconfig) 157e4e2d2f4SJeeja KP { 158e4e2d2f4SJeeja KP struct skl_sst *ctx = skl->skl_sst; 159f6fa56e2SRamesh Babu u8 res_idx = mconfig->res_idx; 160f6fa56e2SRamesh Babu struct skl_module_res *res = &mconfig->module->resources[res_idx]; 161e4e2d2f4SJeeja KP 162f6fa56e2SRamesh Babu if (skl->resource.mcps + res->cps > skl->resource.max_mcps) { 163e4e2d2f4SJeeja KP dev_err(ctx->dev, 164e4e2d2f4SJeeja KP "%s: module_id %d instance %d\n", __func__, 165e4e2d2f4SJeeja KP mconfig->id.module_id, mconfig->id.instance_id); 166e4e2d2f4SJeeja KP dev_err(ctx->dev, 1677ca42f5aSGuneshwor Singh "exceeds ppl mcps available %d > mem %d\n", 168e4e2d2f4SJeeja KP skl->resource.max_mcps, skl->resource.mcps); 169e4e2d2f4SJeeja KP return false; 1709ba8ffefSDharageswari.R } else { 1719ba8ffefSDharageswari.R return true; 1729ba8ffefSDharageswari.R } 173e4e2d2f4SJeeja KP } 174e4e2d2f4SJeeja KP 1759ba8ffefSDharageswari.R static void skl_tplg_alloc_pipe_mcps(struct skl *skl, 1769ba8ffefSDharageswari.R struct skl_module_cfg *mconfig) 1779ba8ffefSDharageswari.R { 178f6fa56e2SRamesh Babu u8 res_idx = mconfig->res_idx; 179f6fa56e2SRamesh Babu struct skl_module_res *res = &mconfig->module->resources[res_idx]; 180f6fa56e2SRamesh Babu 181f6fa56e2SRamesh Babu skl->resource.mcps += res->cps; 182e4e2d2f4SJeeja KP } 183e4e2d2f4SJeeja KP 184e4e2d2f4SJeeja KP /* 185e4e2d2f4SJeeja KP * Free the mcps when tearing down 186e4e2d2f4SJeeja KP */ 187e4e2d2f4SJeeja KP static void 188e4e2d2f4SJeeja KP skl_tplg_free_pipe_mcps(struct skl *skl, struct skl_module_cfg *mconfig) 189e4e2d2f4SJeeja KP { 190f6fa56e2SRamesh Babu u8 res_idx = mconfig->res_idx; 191f6fa56e2SRamesh Babu struct skl_module_res *res = &mconfig->module->resources[res_idx]; 192f6fa56e2SRamesh Babu 193f6fa56e2SRamesh Babu res = &mconfig->module->resources[res_idx]; 194f6fa56e2SRamesh Babu skl->resource.mcps -= res->cps; 195e4e2d2f4SJeeja KP } 196e4e2d2f4SJeeja KP 197e4e2d2f4SJeeja KP /* 198e4e2d2f4SJeeja KP * Free the memory when tearing down 199e4e2d2f4SJeeja KP */ 200e4e2d2f4SJeeja KP static void 201e4e2d2f4SJeeja KP skl_tplg_free_pipe_mem(struct skl *skl, struct skl_module_cfg *mconfig) 202e4e2d2f4SJeeja KP { 203e4e2d2f4SJeeja KP skl->resource.mem -= mconfig->pipe->memory_pages; 204e4e2d2f4SJeeja KP } 205e4e2d2f4SJeeja KP 206f7590d4fSJeeja KP 207f7590d4fSJeeja KP static void skl_dump_mconfig(struct skl_sst *ctx, 208f7590d4fSJeeja KP struct skl_module_cfg *mcfg) 209f7590d4fSJeeja KP { 210f6fa56e2SRamesh Babu struct skl_module_iface *iface = &mcfg->module->formats[0]; 211f6fa56e2SRamesh Babu 212f7590d4fSJeeja KP dev_dbg(ctx->dev, "Dumping config\n"); 213f7590d4fSJeeja KP dev_dbg(ctx->dev, "Input Format:\n"); 214f6fa56e2SRamesh Babu dev_dbg(ctx->dev, "channels = %d\n", iface->inputs[0].fmt.channels); 215f6fa56e2SRamesh Babu dev_dbg(ctx->dev, "s_freq = %d\n", iface->inputs[0].fmt.s_freq); 216f6fa56e2SRamesh Babu dev_dbg(ctx->dev, "ch_cfg = %d\n", iface->inputs[0].fmt.ch_cfg); 217f6fa56e2SRamesh Babu dev_dbg(ctx->dev, "valid bit depth = %d\n", 218f6fa56e2SRamesh Babu iface->inputs[0].fmt.valid_bit_depth); 219f7590d4fSJeeja KP dev_dbg(ctx->dev, "Output Format:\n"); 220f6fa56e2SRamesh Babu dev_dbg(ctx->dev, "channels = %d\n", iface->outputs[0].fmt.channels); 221f6fa56e2SRamesh Babu dev_dbg(ctx->dev, "s_freq = %d\n", iface->outputs[0].fmt.s_freq); 222f6fa56e2SRamesh Babu dev_dbg(ctx->dev, "valid bit depth = %d\n", 223f6fa56e2SRamesh Babu iface->outputs[0].fmt.valid_bit_depth); 224f6fa56e2SRamesh Babu dev_dbg(ctx->dev, "ch_cfg = %d\n", iface->outputs[0].fmt.ch_cfg); 225f7590d4fSJeeja KP } 226f7590d4fSJeeja KP 227ea5a137dSSubhransu S. Prusty static void skl_tplg_update_chmap(struct skl_module_fmt *fmt, int chs) 228ea5a137dSSubhransu S. Prusty { 229ea5a137dSSubhransu S. Prusty int slot_map = 0xFFFFFFFF; 230ea5a137dSSubhransu S. Prusty int start_slot = 0; 231ea5a137dSSubhransu S. Prusty int i; 232ea5a137dSSubhransu S. Prusty 233ea5a137dSSubhransu S. Prusty for (i = 0; i < chs; i++) { 234ea5a137dSSubhransu S. Prusty /* 235ea5a137dSSubhransu S. Prusty * For 2 channels with starting slot as 0, slot map will 236ea5a137dSSubhransu S. Prusty * look like 0xFFFFFF10. 237ea5a137dSSubhransu S. Prusty */ 238ea5a137dSSubhransu S. Prusty slot_map &= (~(0xF << (4 * i)) | (start_slot << (4 * i))); 239ea5a137dSSubhransu S. Prusty start_slot++; 240ea5a137dSSubhransu S. Prusty } 241ea5a137dSSubhransu S. Prusty fmt->ch_map = slot_map; 242ea5a137dSSubhransu S. Prusty } 243ea5a137dSSubhransu S. Prusty 244f7590d4fSJeeja KP static void skl_tplg_update_params(struct skl_module_fmt *fmt, 245f7590d4fSJeeja KP struct skl_pipe_params *params, int fixup) 246f7590d4fSJeeja KP { 247f7590d4fSJeeja KP if (fixup & SKL_RATE_FIXUP_MASK) 248f7590d4fSJeeja KP fmt->s_freq = params->s_freq; 249ea5a137dSSubhransu S. Prusty if (fixup & SKL_CH_FIXUP_MASK) { 250f7590d4fSJeeja KP fmt->channels = params->ch; 251ea5a137dSSubhransu S. Prusty skl_tplg_update_chmap(fmt, fmt->channels); 252ea5a137dSSubhransu S. Prusty } 25398256f83SJeeja KP if (fixup & SKL_FMT_FIXUP_MASK) { 25498256f83SJeeja KP fmt->valid_bit_depth = skl_get_bit_depth(params->s_fmt); 25598256f83SJeeja KP 25698256f83SJeeja KP /* 25798256f83SJeeja KP * 16 bit is 16 bit container whereas 24 bit is in 32 bit 25898256f83SJeeja KP * container so update bit depth accordingly 25998256f83SJeeja KP */ 26098256f83SJeeja KP switch (fmt->valid_bit_depth) { 26198256f83SJeeja KP case SKL_DEPTH_16BIT: 26298256f83SJeeja KP fmt->bit_depth = fmt->valid_bit_depth; 26398256f83SJeeja KP break; 26498256f83SJeeja KP 26598256f83SJeeja KP default: 26698256f83SJeeja KP fmt->bit_depth = SKL_DEPTH_32BIT; 26798256f83SJeeja KP break; 26898256f83SJeeja KP } 26998256f83SJeeja KP } 27098256f83SJeeja KP 271f7590d4fSJeeja KP } 272f7590d4fSJeeja KP 273f7590d4fSJeeja KP /* 274f7590d4fSJeeja KP * A pipeline may have modules which impact the pcm parameters, like SRC, 275f7590d4fSJeeja KP * channel converter, format converter. 276f7590d4fSJeeja KP * We need to calculate the output params by applying the 'fixup' 277f7590d4fSJeeja KP * Topology will tell driver which type of fixup is to be applied by 278f7590d4fSJeeja KP * supplying the fixup mask, so based on that we calculate the output 279f7590d4fSJeeja KP * 280f7590d4fSJeeja KP * Now In FE the pcm hw_params is source/target format. Same is applicable 281f7590d4fSJeeja KP * for BE with its hw_params invoked. 282f7590d4fSJeeja KP * here based on FE, BE pipeline and direction we calculate the input and 283f7590d4fSJeeja KP * outfix and then apply that for a module 284f7590d4fSJeeja KP */ 285f7590d4fSJeeja KP static void skl_tplg_update_params_fixup(struct skl_module_cfg *m_cfg, 286f7590d4fSJeeja KP struct skl_pipe_params *params, bool is_fe) 287f7590d4fSJeeja KP { 288f7590d4fSJeeja KP int in_fixup, out_fixup; 289f7590d4fSJeeja KP struct skl_module_fmt *in_fmt, *out_fmt; 290f7590d4fSJeeja KP 2914cd9899fSHardik T Shah /* Fixups will be applied to pin 0 only */ 292f6fa56e2SRamesh Babu in_fmt = &m_cfg->module->formats[0].inputs[0].fmt; 293f6fa56e2SRamesh Babu out_fmt = &m_cfg->module->formats[0].outputs[0].fmt; 294f7590d4fSJeeja KP 295f7590d4fSJeeja KP if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) { 296f7590d4fSJeeja KP if (is_fe) { 297f7590d4fSJeeja KP in_fixup = m_cfg->params_fixup; 298f7590d4fSJeeja KP out_fixup = (~m_cfg->converter) & 299f7590d4fSJeeja KP m_cfg->params_fixup; 300f7590d4fSJeeja KP } else { 301f7590d4fSJeeja KP out_fixup = m_cfg->params_fixup; 302f7590d4fSJeeja KP in_fixup = (~m_cfg->converter) & 303f7590d4fSJeeja KP m_cfg->params_fixup; 304f7590d4fSJeeja KP } 305f7590d4fSJeeja KP } else { 306f7590d4fSJeeja KP if (is_fe) { 307f7590d4fSJeeja KP out_fixup = m_cfg->params_fixup; 308f7590d4fSJeeja KP in_fixup = (~m_cfg->converter) & 309f7590d4fSJeeja KP m_cfg->params_fixup; 310f7590d4fSJeeja KP } else { 311f7590d4fSJeeja KP in_fixup = m_cfg->params_fixup; 312f7590d4fSJeeja KP out_fixup = (~m_cfg->converter) & 313f7590d4fSJeeja KP m_cfg->params_fixup; 314f7590d4fSJeeja KP } 315f7590d4fSJeeja KP } 316f7590d4fSJeeja KP 317f7590d4fSJeeja KP skl_tplg_update_params(in_fmt, params, in_fixup); 318f7590d4fSJeeja KP skl_tplg_update_params(out_fmt, params, out_fixup); 319f7590d4fSJeeja KP } 320f7590d4fSJeeja KP 321f7590d4fSJeeja KP /* 322f7590d4fSJeeja KP * A module needs input and output buffers, which are dependent upon pcm 323f7590d4fSJeeja KP * params, so once we have calculate params, we need buffer calculation as 324f7590d4fSJeeja KP * well. 325f7590d4fSJeeja KP */ 326f7590d4fSJeeja KP static void skl_tplg_update_buffer_size(struct skl_sst *ctx, 327f7590d4fSJeeja KP struct skl_module_cfg *mcfg) 328f7590d4fSJeeja KP { 329f7590d4fSJeeja KP int multiplier = 1; 3304cd9899fSHardik T Shah struct skl_module_fmt *in_fmt, *out_fmt; 331f6fa56e2SRamesh Babu struct skl_module_res *res; 3324cd9899fSHardik T Shah 3334cd9899fSHardik T Shah /* Since fixups is applied to pin 0 only, ibs, obs needs 3344cd9899fSHardik T Shah * change for pin 0 only 3354cd9899fSHardik T Shah */ 336f6fa56e2SRamesh Babu res = &mcfg->module->resources[0]; 337f6fa56e2SRamesh Babu in_fmt = &mcfg->module->formats[0].inputs[0].fmt; 338f6fa56e2SRamesh Babu out_fmt = &mcfg->module->formats[0].outputs[0].fmt; 339f7590d4fSJeeja KP 340f7590d4fSJeeja KP if (mcfg->m_type == SKL_MODULE_TYPE_SRCINT) 341f7590d4fSJeeja KP multiplier = 5; 342f0c8e1d9SSubhransu S. Prusty 343f6fa56e2SRamesh Babu res->ibs = DIV_ROUND_UP(in_fmt->s_freq, 1000) * 344998d6fb5STakashi Sakamoto in_fmt->channels * (in_fmt->bit_depth >> 3) * 345f7590d4fSJeeja KP multiplier; 346f7590d4fSJeeja KP 347f6fa56e2SRamesh Babu res->obs = DIV_ROUND_UP(out_fmt->s_freq, 1000) * 348998d6fb5STakashi Sakamoto out_fmt->channels * (out_fmt->bit_depth >> 3) * 349f7590d4fSJeeja KP multiplier; 350f7590d4fSJeeja KP } 351f7590d4fSJeeja KP 352db2f586bSSenthilnathan Veppur static u8 skl_tplg_be_dev_type(int dev_type) 353db2f586bSSenthilnathan Veppur { 354db2f586bSSenthilnathan Veppur int ret; 355db2f586bSSenthilnathan Veppur 356db2f586bSSenthilnathan Veppur switch (dev_type) { 357db2f586bSSenthilnathan Veppur case SKL_DEVICE_BT: 358db2f586bSSenthilnathan Veppur ret = NHLT_DEVICE_BT; 359db2f586bSSenthilnathan Veppur break; 360db2f586bSSenthilnathan Veppur 361db2f586bSSenthilnathan Veppur case SKL_DEVICE_DMIC: 362db2f586bSSenthilnathan Veppur ret = NHLT_DEVICE_DMIC; 363db2f586bSSenthilnathan Veppur break; 364db2f586bSSenthilnathan Veppur 365db2f586bSSenthilnathan Veppur case SKL_DEVICE_I2S: 366db2f586bSSenthilnathan Veppur ret = NHLT_DEVICE_I2S; 367db2f586bSSenthilnathan Veppur break; 368db2f586bSSenthilnathan Veppur 369db2f586bSSenthilnathan Veppur default: 370db2f586bSSenthilnathan Veppur ret = NHLT_DEVICE_INVALID; 371db2f586bSSenthilnathan Veppur break; 372db2f586bSSenthilnathan Veppur } 373db2f586bSSenthilnathan Veppur 374db2f586bSSenthilnathan Veppur return ret; 375db2f586bSSenthilnathan Veppur } 376db2f586bSSenthilnathan Veppur 3772d1419a3SJeeja KP static int skl_tplg_update_be_blob(struct snd_soc_dapm_widget *w, 3782d1419a3SJeeja KP struct skl_sst *ctx) 3792d1419a3SJeeja KP { 3802d1419a3SJeeja KP struct skl_module_cfg *m_cfg = w->priv; 3812d1419a3SJeeja KP int link_type, dir; 3822d1419a3SJeeja KP u32 ch, s_freq, s_fmt; 3832d1419a3SJeeja KP struct nhlt_specific_cfg *cfg; 3842d1419a3SJeeja KP struct skl *skl = get_skl_ctx(ctx->dev); 385db2f586bSSenthilnathan Veppur u8 dev_type = skl_tplg_be_dev_type(m_cfg->dev_type); 386f6fa56e2SRamesh Babu int fmt_idx = m_cfg->fmt_idx; 387f6fa56e2SRamesh Babu struct skl_module_iface *m_iface = &m_cfg->module->formats[fmt_idx]; 3882d1419a3SJeeja KP 3892d1419a3SJeeja KP /* check if we already have blob */ 3902d1419a3SJeeja KP if (m_cfg->formats_config.caps_size > 0) 3912d1419a3SJeeja KP return 0; 3922d1419a3SJeeja KP 393c7c6c736SJeeja KP dev_dbg(ctx->dev, "Applying default cfg blob\n"); 3942d1419a3SJeeja KP switch (m_cfg->dev_type) { 3952d1419a3SJeeja KP case SKL_DEVICE_DMIC: 3962d1419a3SJeeja KP link_type = NHLT_LINK_DMIC; 397c7c6c736SJeeja KP dir = SNDRV_PCM_STREAM_CAPTURE; 398f6fa56e2SRamesh Babu s_freq = m_iface->inputs[0].fmt.s_freq; 399f6fa56e2SRamesh Babu s_fmt = m_iface->inputs[0].fmt.bit_depth; 400f6fa56e2SRamesh Babu ch = m_iface->inputs[0].fmt.channels; 4012d1419a3SJeeja KP break; 4022d1419a3SJeeja KP 4032d1419a3SJeeja KP case SKL_DEVICE_I2S: 4042d1419a3SJeeja KP link_type = NHLT_LINK_SSP; 4052d1419a3SJeeja KP if (m_cfg->hw_conn_type == SKL_CONN_SOURCE) { 406c7c6c736SJeeja KP dir = SNDRV_PCM_STREAM_PLAYBACK; 407f6fa56e2SRamesh Babu s_freq = m_iface->outputs[0].fmt.s_freq; 408f6fa56e2SRamesh Babu s_fmt = m_iface->outputs[0].fmt.bit_depth; 409f6fa56e2SRamesh Babu ch = m_iface->outputs[0].fmt.channels; 410c7c6c736SJeeja KP } else { 411c7c6c736SJeeja KP dir = SNDRV_PCM_STREAM_CAPTURE; 412f6fa56e2SRamesh Babu s_freq = m_iface->inputs[0].fmt.s_freq; 413f6fa56e2SRamesh Babu s_fmt = m_iface->inputs[0].fmt.bit_depth; 414f6fa56e2SRamesh Babu ch = m_iface->inputs[0].fmt.channels; 4152d1419a3SJeeja KP } 4162d1419a3SJeeja KP break; 4172d1419a3SJeeja KP 4182d1419a3SJeeja KP default: 4192d1419a3SJeeja KP return -EINVAL; 4202d1419a3SJeeja KP } 4212d1419a3SJeeja KP 4222d1419a3SJeeja KP /* update the blob based on virtual bus_id and default params */ 4232d1419a3SJeeja KP cfg = skl_get_ep_blob(skl, m_cfg->vbus_id, link_type, 424db2f586bSSenthilnathan Veppur s_fmt, ch, s_freq, dir, dev_type); 4252d1419a3SJeeja KP if (cfg) { 4262d1419a3SJeeja KP m_cfg->formats_config.caps_size = cfg->size; 4272d1419a3SJeeja KP m_cfg->formats_config.caps = (u32 *) &cfg->caps; 4282d1419a3SJeeja KP } else { 4292d1419a3SJeeja KP dev_err(ctx->dev, "Blob NULL for id %x type %d dirn %d\n", 4302d1419a3SJeeja KP m_cfg->vbus_id, link_type, dir); 4312d1419a3SJeeja KP dev_err(ctx->dev, "PCM: ch %d, freq %d, fmt %d\n", 4322d1419a3SJeeja KP ch, s_freq, s_fmt); 4332d1419a3SJeeja KP return -EIO; 4342d1419a3SJeeja KP } 4352d1419a3SJeeja KP 4362d1419a3SJeeja KP return 0; 4372d1419a3SJeeja KP } 4382d1419a3SJeeja KP 439f7590d4fSJeeja KP static void skl_tplg_update_module_params(struct snd_soc_dapm_widget *w, 440f7590d4fSJeeja KP struct skl_sst *ctx) 441f7590d4fSJeeja KP { 442f7590d4fSJeeja KP struct skl_module_cfg *m_cfg = w->priv; 443f7590d4fSJeeja KP struct skl_pipe_params *params = m_cfg->pipe->p_params; 444f7590d4fSJeeja KP int p_conn_type = m_cfg->pipe->conn_type; 445f7590d4fSJeeja KP bool is_fe; 446f7590d4fSJeeja KP 447f7590d4fSJeeja KP if (!m_cfg->params_fixup) 448f7590d4fSJeeja KP return; 449f7590d4fSJeeja KP 450f7590d4fSJeeja KP dev_dbg(ctx->dev, "Mconfig for widget=%s BEFORE updation\n", 451f7590d4fSJeeja KP w->name); 452f7590d4fSJeeja KP 453f7590d4fSJeeja KP skl_dump_mconfig(ctx, m_cfg); 454f7590d4fSJeeja KP 455f7590d4fSJeeja KP if (p_conn_type == SKL_PIPE_CONN_TYPE_FE) 456f7590d4fSJeeja KP is_fe = true; 457f7590d4fSJeeja KP else 458f7590d4fSJeeja KP is_fe = false; 459f7590d4fSJeeja KP 460f7590d4fSJeeja KP skl_tplg_update_params_fixup(m_cfg, params, is_fe); 461f7590d4fSJeeja KP skl_tplg_update_buffer_size(ctx, m_cfg); 462f7590d4fSJeeja KP 463f7590d4fSJeeja KP dev_dbg(ctx->dev, "Mconfig for widget=%s AFTER updation\n", 464f7590d4fSJeeja KP w->name); 465f7590d4fSJeeja KP 466f7590d4fSJeeja KP skl_dump_mconfig(ctx, m_cfg); 467f7590d4fSJeeja KP } 468f7590d4fSJeeja KP 469e4e2d2f4SJeeja KP /* 470abb74003SJeeja KP * some modules can have multiple params set from user control and 471abb74003SJeeja KP * need to be set after module is initialized. If set_param flag is 472abb74003SJeeja KP * set module params will be done after module is initialised. 473abb74003SJeeja KP */ 474abb74003SJeeja KP static int skl_tplg_set_module_params(struct snd_soc_dapm_widget *w, 475abb74003SJeeja KP struct skl_sst *ctx) 476abb74003SJeeja KP { 477abb74003SJeeja KP int i, ret; 478abb74003SJeeja KP struct skl_module_cfg *mconfig = w->priv; 479abb74003SJeeja KP const struct snd_kcontrol_new *k; 480abb74003SJeeja KP struct soc_bytes_ext *sb; 481abb74003SJeeja KP struct skl_algo_data *bc; 482abb74003SJeeja KP struct skl_specific_cfg *sp_cfg; 483abb74003SJeeja KP 484abb74003SJeeja KP if (mconfig->formats_config.caps_size > 0 && 4854ced1827SJeeja KP mconfig->formats_config.set_params == SKL_PARAM_SET) { 486abb74003SJeeja KP sp_cfg = &mconfig->formats_config; 487abb74003SJeeja KP ret = skl_set_module_params(ctx, sp_cfg->caps, 488abb74003SJeeja KP sp_cfg->caps_size, 489abb74003SJeeja KP sp_cfg->param_id, mconfig); 490abb74003SJeeja KP if (ret < 0) 491abb74003SJeeja KP return ret; 492abb74003SJeeja KP } 493abb74003SJeeja KP 494abb74003SJeeja KP for (i = 0; i < w->num_kcontrols; i++) { 495abb74003SJeeja KP k = &w->kcontrol_news[i]; 496abb74003SJeeja KP if (k->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { 497abb74003SJeeja KP sb = (void *) k->private_value; 498abb74003SJeeja KP bc = (struct skl_algo_data *)sb->dobj.private; 499abb74003SJeeja KP 5004ced1827SJeeja KP if (bc->set_params == SKL_PARAM_SET) { 501abb74003SJeeja KP ret = skl_set_module_params(ctx, 5020d682104SDharageswari R (u32 *)bc->params, bc->size, 503abb74003SJeeja KP bc->param_id, mconfig); 504abb74003SJeeja KP if (ret < 0) 505abb74003SJeeja KP return ret; 506abb74003SJeeja KP } 507abb74003SJeeja KP } 508abb74003SJeeja KP } 509abb74003SJeeja KP 510abb74003SJeeja KP return 0; 511abb74003SJeeja KP } 512abb74003SJeeja KP 513abb74003SJeeja KP /* 514abb74003SJeeja KP * some module param can set from user control and this is required as 515abb74003SJeeja KP * when module is initailzed. if module param is required in init it is 516abb74003SJeeja KP * identifed by set_param flag. if set_param flag is not set, then this 517abb74003SJeeja KP * parameter needs to set as part of module init. 518abb74003SJeeja KP */ 519abb74003SJeeja KP static int skl_tplg_set_module_init_data(struct snd_soc_dapm_widget *w) 520abb74003SJeeja KP { 521abb74003SJeeja KP const struct snd_kcontrol_new *k; 522abb74003SJeeja KP struct soc_bytes_ext *sb; 523abb74003SJeeja KP struct skl_algo_data *bc; 524abb74003SJeeja KP struct skl_module_cfg *mconfig = w->priv; 525abb74003SJeeja KP int i; 526abb74003SJeeja KP 527abb74003SJeeja KP for (i = 0; i < w->num_kcontrols; i++) { 528abb74003SJeeja KP k = &w->kcontrol_news[i]; 529abb74003SJeeja KP if (k->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { 530abb74003SJeeja KP sb = (struct soc_bytes_ext *)k->private_value; 531abb74003SJeeja KP bc = (struct skl_algo_data *)sb->dobj.private; 532abb74003SJeeja KP 5334ced1827SJeeja KP if (bc->set_params != SKL_PARAM_INIT) 534abb74003SJeeja KP continue; 535abb74003SJeeja KP 536d1a6fe41STakashi Sakamoto mconfig->formats_config.caps = (u32 *)bc->params; 5370d682104SDharageswari R mconfig->formats_config.caps_size = bc->size; 538abb74003SJeeja KP 539abb74003SJeeja KP break; 540abb74003SJeeja KP } 541abb74003SJeeja KP } 542abb74003SJeeja KP 543abb74003SJeeja KP return 0; 544abb74003SJeeja KP } 545abb74003SJeeja KP 546bb704a73SJeeja KP static int skl_tplg_module_prepare(struct skl_sst *ctx, struct skl_pipe *pipe, 547bb704a73SJeeja KP struct snd_soc_dapm_widget *w, struct skl_module_cfg *mcfg) 548bb704a73SJeeja KP { 549bb704a73SJeeja KP switch (mcfg->dev_type) { 550bb704a73SJeeja KP case SKL_DEVICE_HDAHOST: 551bb704a73SJeeja KP return skl_pcm_host_dma_prepare(ctx->dev, pipe->p_params); 552bb704a73SJeeja KP 553bb704a73SJeeja KP case SKL_DEVICE_HDALINK: 554bb704a73SJeeja KP return skl_pcm_link_dma_prepare(ctx->dev, pipe->p_params); 555bb704a73SJeeja KP } 556bb704a73SJeeja KP 557bb704a73SJeeja KP return 0; 558bb704a73SJeeja KP } 559bb704a73SJeeja KP 560abb74003SJeeja KP /* 561e4e2d2f4SJeeja KP * Inside a pipe instance, we can have various modules. These modules need 562e4e2d2f4SJeeja KP * to instantiated in DSP by invoking INIT_MODULE IPC, which is achieved by 563e4e2d2f4SJeeja KP * skl_init_module() routine, so invoke that for all modules in a pipeline 564e4e2d2f4SJeeja KP */ 565e4e2d2f4SJeeja KP static int 566e4e2d2f4SJeeja KP skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe) 567e4e2d2f4SJeeja KP { 568e4e2d2f4SJeeja KP struct skl_pipe_module *w_module; 569e4e2d2f4SJeeja KP struct snd_soc_dapm_widget *w; 570e4e2d2f4SJeeja KP struct skl_module_cfg *mconfig; 571e4e2d2f4SJeeja KP struct skl_sst *ctx = skl->skl_sst; 572f6fa56e2SRamesh Babu u8 cfg_idx; 573e4e2d2f4SJeeja KP int ret = 0; 574e4e2d2f4SJeeja KP 575e4e2d2f4SJeeja KP list_for_each_entry(w_module, &pipe->w_list, node) { 576b26199eaSJeeja KP uuid_le *uuid_mod; 577e4e2d2f4SJeeja KP w = w_module->w; 578e4e2d2f4SJeeja KP mconfig = w->priv; 579e4e2d2f4SJeeja KP 580b7c50555SVinod Koul /* check if module ids are populated */ 581b7c50555SVinod Koul if (mconfig->id.module_id < 0) { 582b7c50555SVinod Koul dev_err(skl->skl_sst->dev, 583a657ae7eSVinod Koul "module %pUL id not populated\n", 584a657ae7eSVinod Koul (uuid_le *)mconfig->guid); 585a657ae7eSVinod Koul return -EIO; 586b7c50555SVinod Koul } 587b7c50555SVinod Koul 588f6fa56e2SRamesh Babu cfg_idx = mconfig->pipe->cur_config_idx; 589f6fa56e2SRamesh Babu mconfig->fmt_idx = mconfig->mod_cfg[cfg_idx].fmt_idx; 590f6fa56e2SRamesh Babu mconfig->res_idx = mconfig->mod_cfg[cfg_idx].res_idx; 591f6fa56e2SRamesh Babu 592e4e2d2f4SJeeja KP /* check resource available */ 5939ba8ffefSDharageswari.R if (!skl_is_pipe_mcps_avail(skl, mconfig)) 594e4e2d2f4SJeeja KP return -ENOMEM; 595e4e2d2f4SJeeja KP 596f6fa56e2SRamesh Babu if (mconfig->module->loadable && ctx->dsp->fw_ops.load_mod) { 5976c5768b3SDharageswari R ret = ctx->dsp->fw_ops.load_mod(ctx->dsp, 5986c5768b3SDharageswari R mconfig->id.module_id, mconfig->guid); 5996c5768b3SDharageswari R if (ret < 0) 6006c5768b3SDharageswari R return ret; 601d643678bSJeeja KP 602d643678bSJeeja KP mconfig->m_state = SKL_MODULE_LOADED; 6036c5768b3SDharageswari R } 6046c5768b3SDharageswari R 605bb704a73SJeeja KP /* prepare the DMA if the module is gateway cpr */ 606bb704a73SJeeja KP ret = skl_tplg_module_prepare(ctx, pipe, w, mconfig); 607bb704a73SJeeja KP if (ret < 0) 608bb704a73SJeeja KP return ret; 609bb704a73SJeeja KP 6102d1419a3SJeeja KP /* update blob if blob is null for be with default value */ 6112d1419a3SJeeja KP skl_tplg_update_be_blob(w, ctx); 6122d1419a3SJeeja KP 613f7590d4fSJeeja KP /* 614f7590d4fSJeeja KP * apply fix/conversion to module params based on 615f7590d4fSJeeja KP * FE/BE params 616f7590d4fSJeeja KP */ 617f7590d4fSJeeja KP skl_tplg_update_module_params(w, ctx); 618b26199eaSJeeja KP uuid_mod = (uuid_le *)mconfig->guid; 619b26199eaSJeeja KP mconfig->id.pvt_id = skl_get_pvt_id(ctx, uuid_mod, 620b26199eaSJeeja KP mconfig->id.instance_id); 621ef2a352cSDharageswari R if (mconfig->id.pvt_id < 0) 622ef2a352cSDharageswari R return ret; 623abb74003SJeeja KP skl_tplg_set_module_init_data(w); 6244147a6e5SPardha Saradhi K 6254147a6e5SPardha Saradhi K ret = skl_dsp_get_core(ctx->dsp, mconfig->core_id); 6264147a6e5SPardha Saradhi K if (ret < 0) { 6274147a6e5SPardha Saradhi K dev_err(ctx->dev, "Failed to wake up core %d ret=%d\n", 6284147a6e5SPardha Saradhi K mconfig->core_id, ret); 6294147a6e5SPardha Saradhi K return ret; 6304147a6e5SPardha Saradhi K } 6314147a6e5SPardha Saradhi K 6329939a9c3SJeeja KP ret = skl_init_module(ctx, mconfig); 633ef2a352cSDharageswari R if (ret < 0) { 634b26199eaSJeeja KP skl_put_pvt_id(ctx, uuid_mod, &mconfig->id.pvt_id); 6354147a6e5SPardha Saradhi K goto err; 636ef2a352cSDharageswari R } 637260eb73aSDharageswari R skl_tplg_alloc_pipe_mcps(skl, mconfig); 638abb74003SJeeja KP ret = skl_tplg_set_module_params(w, ctx); 639e4e2d2f4SJeeja KP if (ret < 0) 6404147a6e5SPardha Saradhi K goto err; 641e4e2d2f4SJeeja KP } 642e4e2d2f4SJeeja KP 643e4e2d2f4SJeeja KP return 0; 6444147a6e5SPardha Saradhi K err: 6454147a6e5SPardha Saradhi K skl_dsp_put_core(ctx->dsp, mconfig->core_id); 6464147a6e5SPardha Saradhi K return ret; 647e4e2d2f4SJeeja KP } 648d93f8e55SVinod Koul 6496c5768b3SDharageswari R static int skl_tplg_unload_pipe_modules(struct skl_sst *ctx, 6506c5768b3SDharageswari R struct skl_pipe *pipe) 6516c5768b3SDharageswari R { 6524147a6e5SPardha Saradhi K int ret = 0; 6536c5768b3SDharageswari R struct skl_pipe_module *w_module = NULL; 6546c5768b3SDharageswari R struct skl_module_cfg *mconfig = NULL; 6556c5768b3SDharageswari R 6566c5768b3SDharageswari R list_for_each_entry(w_module, &pipe->w_list, node) { 657b26199eaSJeeja KP uuid_le *uuid_mod; 6586c5768b3SDharageswari R mconfig = w_module->w->priv; 659b26199eaSJeeja KP uuid_mod = (uuid_le *)mconfig->guid; 6606c5768b3SDharageswari R 661f6fa56e2SRamesh Babu if (mconfig->module->loadable && ctx->dsp->fw_ops.unload_mod && 662b0fab9c6SDharageswari R mconfig->m_state > SKL_MODULE_UNINIT) { 663b0fab9c6SDharageswari R ret = ctx->dsp->fw_ops.unload_mod(ctx->dsp, 6646c5768b3SDharageswari R mconfig->id.module_id); 665b0fab9c6SDharageswari R if (ret < 0) 666b0fab9c6SDharageswari R return -EIO; 667b0fab9c6SDharageswari R } 668b26199eaSJeeja KP skl_put_pvt_id(ctx, uuid_mod, &mconfig->id.pvt_id); 6694147a6e5SPardha Saradhi K 6704147a6e5SPardha Saradhi K ret = skl_dsp_put_core(ctx->dsp, mconfig->core_id); 6714147a6e5SPardha Saradhi K if (ret < 0) { 6724147a6e5SPardha Saradhi K /* don't return; continue with other modules */ 6734147a6e5SPardha Saradhi K dev_err(ctx->dev, "Failed to sleep core %d ret=%d\n", 6744147a6e5SPardha Saradhi K mconfig->core_id, ret); 6754147a6e5SPardha Saradhi K } 6766c5768b3SDharageswari R } 6776c5768b3SDharageswari R 6786c5768b3SDharageswari R /* no modules to unload in this path, so return */ 6794147a6e5SPardha Saradhi K return ret; 6806c5768b3SDharageswari R } 6816c5768b3SDharageswari R 682d93f8e55SVinod Koul /* 683f6fa56e2SRamesh Babu * Here, we select pipe format based on the pipe type and pipe 684f6fa56e2SRamesh Babu * direction to determine the current config index for the pipeline. 685f6fa56e2SRamesh Babu * The config index is then used to select proper module resources. 686f6fa56e2SRamesh Babu * Intermediate pipes currently have a fixed format hence we select the 687f6fa56e2SRamesh Babu * 0th configuratation by default for such pipes. 688f6fa56e2SRamesh Babu */ 689f6fa56e2SRamesh Babu static int 690f6fa56e2SRamesh Babu skl_tplg_get_pipe_config(struct skl *skl, struct skl_module_cfg *mconfig) 691f6fa56e2SRamesh Babu { 692f6fa56e2SRamesh Babu struct skl_sst *ctx = skl->skl_sst; 693f6fa56e2SRamesh Babu struct skl_pipe *pipe = mconfig->pipe; 694f6fa56e2SRamesh Babu struct skl_pipe_params *params = pipe->p_params; 695f6fa56e2SRamesh Babu struct skl_path_config *pconfig = &pipe->configs[0]; 696f6fa56e2SRamesh Babu struct skl_pipe_fmt *fmt = NULL; 697f6fa56e2SRamesh Babu bool in_fmt = false; 698f6fa56e2SRamesh Babu int i; 699f6fa56e2SRamesh Babu 700f6fa56e2SRamesh Babu if (pipe->nr_cfgs == 0) { 701f6fa56e2SRamesh Babu pipe->cur_config_idx = 0; 702f6fa56e2SRamesh Babu return 0; 703f6fa56e2SRamesh Babu } 704f6fa56e2SRamesh Babu 705f6fa56e2SRamesh Babu if (pipe->conn_type == SKL_PIPE_CONN_TYPE_NONE) { 706f6fa56e2SRamesh Babu dev_dbg(ctx->dev, "No conn_type detected, take 0th config\n"); 707f6fa56e2SRamesh Babu pipe->cur_config_idx = 0; 708f6fa56e2SRamesh Babu pipe->memory_pages = pconfig->mem_pages; 709f6fa56e2SRamesh Babu 710f6fa56e2SRamesh Babu return 0; 711f6fa56e2SRamesh Babu } 712f6fa56e2SRamesh Babu 713f6fa56e2SRamesh Babu if ((pipe->conn_type == SKL_PIPE_CONN_TYPE_FE && 714f6fa56e2SRamesh Babu pipe->direction == SNDRV_PCM_STREAM_PLAYBACK) || 715f6fa56e2SRamesh Babu (pipe->conn_type == SKL_PIPE_CONN_TYPE_BE && 716f6fa56e2SRamesh Babu pipe->direction == SNDRV_PCM_STREAM_CAPTURE)) 717f6fa56e2SRamesh Babu in_fmt = true; 718f6fa56e2SRamesh Babu 719f6fa56e2SRamesh Babu for (i = 0; i < pipe->nr_cfgs; i++) { 720f6fa56e2SRamesh Babu pconfig = &pipe->configs[i]; 721f6fa56e2SRamesh Babu if (in_fmt) 722f6fa56e2SRamesh Babu fmt = &pconfig->in_fmt; 723f6fa56e2SRamesh Babu else 724f6fa56e2SRamesh Babu fmt = &pconfig->out_fmt; 725f6fa56e2SRamesh Babu 726f6fa56e2SRamesh Babu if (CHECK_HW_PARAMS(params->ch, params->s_freq, params->s_fmt, 727f6fa56e2SRamesh Babu fmt->channels, fmt->freq, fmt->bps)) { 728f6fa56e2SRamesh Babu pipe->cur_config_idx = i; 729f6fa56e2SRamesh Babu pipe->memory_pages = pconfig->mem_pages; 730f6fa56e2SRamesh Babu dev_dbg(ctx->dev, "Using pipe config: %d\n", i); 731f6fa56e2SRamesh Babu 732f6fa56e2SRamesh Babu return 0; 733f6fa56e2SRamesh Babu } 734f6fa56e2SRamesh Babu } 735f6fa56e2SRamesh Babu 736f6fa56e2SRamesh Babu dev_err(ctx->dev, "Invalid pipe config: %d %d %d for pipe: %d\n", 737f6fa56e2SRamesh Babu params->ch, params->s_freq, params->s_fmt, pipe->ppl_id); 738f6fa56e2SRamesh Babu return -EINVAL; 739f6fa56e2SRamesh Babu } 740f6fa56e2SRamesh Babu 741f6fa56e2SRamesh Babu /* 742d93f8e55SVinod Koul * Mixer module represents a pipeline. So in the Pre-PMU event of mixer we 743d93f8e55SVinod Koul * need create the pipeline. So we do following: 744d93f8e55SVinod Koul * - check the resources 745d93f8e55SVinod Koul * - Create the pipeline 746d93f8e55SVinod Koul * - Initialize the modules in pipeline 747d93f8e55SVinod Koul * - finally bind all modules together 748d93f8e55SVinod Koul */ 749d93f8e55SVinod Koul static int skl_tplg_mixer_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w, 750d93f8e55SVinod Koul struct skl *skl) 751d93f8e55SVinod Koul { 752d93f8e55SVinod Koul int ret; 753d93f8e55SVinod Koul struct skl_module_cfg *mconfig = w->priv; 754d93f8e55SVinod Koul struct skl_pipe_module *w_module; 755d93f8e55SVinod Koul struct skl_pipe *s_pipe = mconfig->pipe; 756b8c722ddSJeeja KP struct skl_module_cfg *src_module = NULL, *dst_module, *module; 757d93f8e55SVinod Koul struct skl_sst *ctx = skl->skl_sst; 758b8c722ddSJeeja KP struct skl_module_deferred_bind *modules; 759d93f8e55SVinod Koul 760f6fa56e2SRamesh Babu ret = skl_tplg_get_pipe_config(skl, mconfig); 761f6fa56e2SRamesh Babu if (ret < 0) 762f6fa56e2SRamesh Babu return ret; 763f6fa56e2SRamesh Babu 764d93f8e55SVinod Koul /* check resource available */ 7659ba8ffefSDharageswari.R if (!skl_is_pipe_mcps_avail(skl, mconfig)) 766d93f8e55SVinod Koul return -EBUSY; 767d93f8e55SVinod Koul 7689ba8ffefSDharageswari.R if (!skl_is_pipe_mem_avail(skl, mconfig)) 769d93f8e55SVinod Koul return -ENOMEM; 770d93f8e55SVinod Koul 771d93f8e55SVinod Koul /* 772d93f8e55SVinod Koul * Create a list of modules for pipe. 773d93f8e55SVinod Koul * This list contains modules from source to sink 774d93f8e55SVinod Koul */ 775d93f8e55SVinod Koul ret = skl_create_pipeline(ctx, mconfig->pipe); 776d93f8e55SVinod Koul if (ret < 0) 777d93f8e55SVinod Koul return ret; 778d93f8e55SVinod Koul 779260eb73aSDharageswari R skl_tplg_alloc_pipe_mem(skl, mconfig); 780260eb73aSDharageswari R skl_tplg_alloc_pipe_mcps(skl, mconfig); 781d93f8e55SVinod Koul 782d93f8e55SVinod Koul /* Init all pipe modules from source to sink */ 783d93f8e55SVinod Koul ret = skl_tplg_init_pipe_modules(skl, s_pipe); 784d93f8e55SVinod Koul if (ret < 0) 785d93f8e55SVinod Koul return ret; 786d93f8e55SVinod Koul 787d93f8e55SVinod Koul /* Bind modules from source to sink */ 788d93f8e55SVinod Koul list_for_each_entry(w_module, &s_pipe->w_list, node) { 789d93f8e55SVinod Koul dst_module = w_module->w->priv; 790d93f8e55SVinod Koul 791d93f8e55SVinod Koul if (src_module == NULL) { 792d93f8e55SVinod Koul src_module = dst_module; 793d93f8e55SVinod Koul continue; 794d93f8e55SVinod Koul } 795d93f8e55SVinod Koul 796d93f8e55SVinod Koul ret = skl_bind_modules(ctx, src_module, dst_module); 797d93f8e55SVinod Koul if (ret < 0) 798d93f8e55SVinod Koul return ret; 799d93f8e55SVinod Koul 800d93f8e55SVinod Koul src_module = dst_module; 801d93f8e55SVinod Koul } 802d93f8e55SVinod Koul 803b8c722ddSJeeja KP /* 804b8c722ddSJeeja KP * When the destination module is initialized, check for these modules 805b8c722ddSJeeja KP * in deferred bind list. If found, bind them. 806b8c722ddSJeeja KP */ 807b8c722ddSJeeja KP list_for_each_entry(w_module, &s_pipe->w_list, node) { 808b8c722ddSJeeja KP if (list_empty(&skl->bind_list)) 809b8c722ddSJeeja KP break; 810b8c722ddSJeeja KP 811b8c722ddSJeeja KP list_for_each_entry(modules, &skl->bind_list, node) { 812b8c722ddSJeeja KP module = w_module->w->priv; 813b8c722ddSJeeja KP if (modules->dst == module) 814b8c722ddSJeeja KP skl_bind_modules(ctx, modules->src, 815b8c722ddSJeeja KP modules->dst); 816b8c722ddSJeeja KP } 817b8c722ddSJeeja KP } 818b8c722ddSJeeja KP 819d93f8e55SVinod Koul return 0; 820d93f8e55SVinod Koul } 821d93f8e55SVinod Koul 822bf3e5ef5SDharageswari R static int skl_fill_sink_instance_id(struct skl_sst *ctx, u32 *params, 823bf3e5ef5SDharageswari R int size, struct skl_module_cfg *mcfg) 8245e8f0ee4SDharageswari R { 8255e8f0ee4SDharageswari R int i, pvt_id; 8265e8f0ee4SDharageswari R 827bf3e5ef5SDharageswari R if (mcfg->m_type == SKL_MODULE_TYPE_KPB) { 828bf3e5ef5SDharageswari R struct skl_kpb_params *kpb_params = 829bf3e5ef5SDharageswari R (struct skl_kpb_params *)params; 830bf3e5ef5SDharageswari R struct skl_mod_inst_map *inst = kpb_params->map; 8315e8f0ee4SDharageswari R 832bf3e5ef5SDharageswari R for (i = 0; i < kpb_params->num_modules; i++) { 833bf3e5ef5SDharageswari R pvt_id = skl_get_pvt_instance_id_map(ctx, inst->mod_id, 834bf3e5ef5SDharageswari R inst->inst_id); 8355e8f0ee4SDharageswari R if (pvt_id < 0) 8365e8f0ee4SDharageswari R return -EINVAL; 837bf3e5ef5SDharageswari R 8385e8f0ee4SDharageswari R inst->inst_id = pvt_id; 8395e8f0ee4SDharageswari R inst++; 8405e8f0ee4SDharageswari R } 8415e8f0ee4SDharageswari R } 8425e8f0ee4SDharageswari R 843bf3e5ef5SDharageswari R return 0; 844bf3e5ef5SDharageswari R } 845cc6a4044SJeeja KP /* 846cc6a4044SJeeja KP * Some modules require params to be set after the module is bound to 847cc6a4044SJeeja KP * all pins connected. 848cc6a4044SJeeja KP * 849cc6a4044SJeeja KP * The module provider initializes set_param flag for such modules and we 850cc6a4044SJeeja KP * send params after binding 851cc6a4044SJeeja KP */ 852cc6a4044SJeeja KP static int skl_tplg_set_module_bind_params(struct snd_soc_dapm_widget *w, 853cc6a4044SJeeja KP struct skl_module_cfg *mcfg, struct skl_sst *ctx) 854cc6a4044SJeeja KP { 855cc6a4044SJeeja KP int i, ret; 856cc6a4044SJeeja KP struct skl_module_cfg *mconfig = w->priv; 857cc6a4044SJeeja KP const struct snd_kcontrol_new *k; 858cc6a4044SJeeja KP struct soc_bytes_ext *sb; 859cc6a4044SJeeja KP struct skl_algo_data *bc; 860cc6a4044SJeeja KP struct skl_specific_cfg *sp_cfg; 861bf3e5ef5SDharageswari R u32 *params; 862cc6a4044SJeeja KP 863cc6a4044SJeeja KP /* 864cc6a4044SJeeja KP * check all out/in pins are in bind state. 865cc6a4044SJeeja KP * if so set the module param 866cc6a4044SJeeja KP */ 867f6fa56e2SRamesh Babu for (i = 0; i < mcfg->module->max_output_pins; i++) { 868cc6a4044SJeeja KP if (mcfg->m_out_pin[i].pin_state != SKL_PIN_BIND_DONE) 869cc6a4044SJeeja KP return 0; 870cc6a4044SJeeja KP } 871cc6a4044SJeeja KP 872f6fa56e2SRamesh Babu for (i = 0; i < mcfg->module->max_input_pins; i++) { 873cc6a4044SJeeja KP if (mcfg->m_in_pin[i].pin_state != SKL_PIN_BIND_DONE) 874cc6a4044SJeeja KP return 0; 875cc6a4044SJeeja KP } 876cc6a4044SJeeja KP 877cc6a4044SJeeja KP if (mconfig->formats_config.caps_size > 0 && 878cc6a4044SJeeja KP mconfig->formats_config.set_params == SKL_PARAM_BIND) { 879cc6a4044SJeeja KP sp_cfg = &mconfig->formats_config; 880cc6a4044SJeeja KP ret = skl_set_module_params(ctx, sp_cfg->caps, 881cc6a4044SJeeja KP sp_cfg->caps_size, 882cc6a4044SJeeja KP sp_cfg->param_id, mconfig); 883cc6a4044SJeeja KP if (ret < 0) 884cc6a4044SJeeja KP return ret; 885cc6a4044SJeeja KP } 886cc6a4044SJeeja KP 887cc6a4044SJeeja KP for (i = 0; i < w->num_kcontrols; i++) { 888cc6a4044SJeeja KP k = &w->kcontrol_news[i]; 889cc6a4044SJeeja KP if (k->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { 890cc6a4044SJeeja KP sb = (void *) k->private_value; 891cc6a4044SJeeja KP bc = (struct skl_algo_data *)sb->dobj.private; 892cc6a4044SJeeja KP 893cc6a4044SJeeja KP if (bc->set_params == SKL_PARAM_BIND) { 894bf3e5ef5SDharageswari R params = kzalloc(bc->max, GFP_KERNEL); 895bf3e5ef5SDharageswari R if (!params) 896bf3e5ef5SDharageswari R return -ENOMEM; 897bf3e5ef5SDharageswari R 898bf3e5ef5SDharageswari R memcpy(params, bc->params, bc->max); 899bf3e5ef5SDharageswari R skl_fill_sink_instance_id(ctx, params, bc->max, 900bf3e5ef5SDharageswari R mconfig); 901bf3e5ef5SDharageswari R 902bf3e5ef5SDharageswari R ret = skl_set_module_params(ctx, params, 903bf3e5ef5SDharageswari R bc->max, bc->param_id, mconfig); 904bf3e5ef5SDharageswari R kfree(params); 905bf3e5ef5SDharageswari R 906cc6a4044SJeeja KP if (ret < 0) 907cc6a4044SJeeja KP return ret; 908cc6a4044SJeeja KP } 909cc6a4044SJeeja KP } 910cc6a4044SJeeja KP } 911cc6a4044SJeeja KP 912cc6a4044SJeeja KP return 0; 913cc6a4044SJeeja KP } 914cc6a4044SJeeja KP 915b8c722ddSJeeja KP 916b8c722ddSJeeja KP static int skl_tplg_module_add_deferred_bind(struct skl *skl, 917b8c722ddSJeeja KP struct skl_module_cfg *src, struct skl_module_cfg *dst) 918b8c722ddSJeeja KP { 919b8c722ddSJeeja KP struct skl_module_deferred_bind *m_list, *modules; 920b8c722ddSJeeja KP int i; 921b8c722ddSJeeja KP 922b8c722ddSJeeja KP /* only supported for module with static pin connection */ 923f6fa56e2SRamesh Babu for (i = 0; i < dst->module->max_input_pins; i++) { 924b8c722ddSJeeja KP struct skl_module_pin *pin = &dst->m_in_pin[i]; 925b8c722ddSJeeja KP 926b8c722ddSJeeja KP if (pin->is_dynamic) 927b8c722ddSJeeja KP continue; 928b8c722ddSJeeja KP 929b8c722ddSJeeja KP if ((pin->id.module_id == src->id.module_id) && 930b8c722ddSJeeja KP (pin->id.instance_id == src->id.instance_id)) { 931b8c722ddSJeeja KP 932b8c722ddSJeeja KP if (!list_empty(&skl->bind_list)) { 933b8c722ddSJeeja KP list_for_each_entry(modules, &skl->bind_list, node) { 934b8c722ddSJeeja KP if (modules->src == src && modules->dst == dst) 935b8c722ddSJeeja KP return 0; 936b8c722ddSJeeja KP } 937b8c722ddSJeeja KP } 938b8c722ddSJeeja KP 939b8c722ddSJeeja KP m_list = kzalloc(sizeof(*m_list), GFP_KERNEL); 940b8c722ddSJeeja KP if (!m_list) 941b8c722ddSJeeja KP return -ENOMEM; 942b8c722ddSJeeja KP 943b8c722ddSJeeja KP m_list->src = src; 944b8c722ddSJeeja KP m_list->dst = dst; 945b8c722ddSJeeja KP 946b8c722ddSJeeja KP list_add(&m_list->node, &skl->bind_list); 947b8c722ddSJeeja KP } 948b8c722ddSJeeja KP } 949b8c722ddSJeeja KP 950b8c722ddSJeeja KP return 0; 951b8c722ddSJeeja KP } 952b8c722ddSJeeja KP 9538724ff17SJeeja KP static int skl_tplg_bind_sinks(struct snd_soc_dapm_widget *w, 9548724ff17SJeeja KP struct skl *skl, 9556bd4cf85SJeeja KP struct snd_soc_dapm_widget *src_w, 9568724ff17SJeeja KP struct skl_module_cfg *src_mconfig) 957d93f8e55SVinod Koul { 958d93f8e55SVinod Koul struct snd_soc_dapm_path *p; 9590ed95d76SJeeja KP struct snd_soc_dapm_widget *sink = NULL, *next_sink = NULL; 9608724ff17SJeeja KP struct skl_module_cfg *sink_mconfig; 961d93f8e55SVinod Koul struct skl_sst *ctx = skl->skl_sst; 9628724ff17SJeeja KP int ret; 963d93f8e55SVinod Koul 9648724ff17SJeeja KP snd_soc_dapm_widget_for_each_sink_path(w, p) { 965d93f8e55SVinod Koul if (!p->connect) 966d93f8e55SVinod Koul continue; 967d93f8e55SVinod Koul 968d93f8e55SVinod Koul dev_dbg(ctx->dev, "%s: src widget=%s\n", __func__, w->name); 969d93f8e55SVinod Koul dev_dbg(ctx->dev, "%s: sink widget=%s\n", __func__, p->sink->name); 970d93f8e55SVinod Koul 9710ed95d76SJeeja KP next_sink = p->sink; 9726bd4cf85SJeeja KP 9736bd4cf85SJeeja KP if (!is_skl_dsp_widget_type(p->sink)) 9746bd4cf85SJeeja KP return skl_tplg_bind_sinks(p->sink, skl, src_w, src_mconfig); 9756bd4cf85SJeeja KP 976d93f8e55SVinod Koul /* 977d93f8e55SVinod Koul * here we will check widgets in sink pipelines, so that 978d93f8e55SVinod Koul * can be any widgets type and we are only interested if 979d93f8e55SVinod Koul * they are ones used for SKL so check that first 980d93f8e55SVinod Koul */ 981d93f8e55SVinod Koul if ((p->sink->priv != NULL) && 982d93f8e55SVinod Koul is_skl_dsp_widget_type(p->sink)) { 983d93f8e55SVinod Koul 984d93f8e55SVinod Koul sink = p->sink; 985d93f8e55SVinod Koul sink_mconfig = sink->priv; 986d93f8e55SVinod Koul 987b8c722ddSJeeja KP /* 988b8c722ddSJeeja KP * Modules other than PGA leaf can be connected 989b8c722ddSJeeja KP * directly or via switch to a module in another 990b8c722ddSJeeja KP * pipeline. EX: reference path 991b8c722ddSJeeja KP * when the path is enabled, the dst module that needs 992b8c722ddSJeeja KP * to be bound may not be initialized. if the module is 993b8c722ddSJeeja KP * not initialized, add these modules in the deferred 994b8c722ddSJeeja KP * bind list and when the dst module is initialised, 995b8c722ddSJeeja KP * bind this module to the dst_module in deferred list. 996b8c722ddSJeeja KP */ 997b8c722ddSJeeja KP if (((src_mconfig->m_state == SKL_MODULE_INIT_DONE) 998b8c722ddSJeeja KP && (sink_mconfig->m_state == SKL_MODULE_UNINIT))) { 999b8c722ddSJeeja KP 1000b8c722ddSJeeja KP ret = skl_tplg_module_add_deferred_bind(skl, 1001b8c722ddSJeeja KP src_mconfig, sink_mconfig); 1002b8c722ddSJeeja KP 1003b8c722ddSJeeja KP if (ret < 0) 1004b8c722ddSJeeja KP return ret; 1005b8c722ddSJeeja KP 1006b8c722ddSJeeja KP } 1007b8c722ddSJeeja KP 1008b8c722ddSJeeja KP 1009cc6a4044SJeeja KP if (src_mconfig->m_state == SKL_MODULE_UNINIT || 1010cc6a4044SJeeja KP sink_mconfig->m_state == SKL_MODULE_UNINIT) 1011cc6a4044SJeeja KP continue; 1012cc6a4044SJeeja KP 1013d93f8e55SVinod Koul /* Bind source to sink, mixin is always source */ 1014d93f8e55SVinod Koul ret = skl_bind_modules(ctx, src_mconfig, sink_mconfig); 1015d93f8e55SVinod Koul if (ret) 1016d93f8e55SVinod Koul return ret; 1017d93f8e55SVinod Koul 1018cc6a4044SJeeja KP /* set module params after bind */ 1019cc6a4044SJeeja KP skl_tplg_set_module_bind_params(src_w, src_mconfig, ctx); 1020cc6a4044SJeeja KP skl_tplg_set_module_bind_params(sink, sink_mconfig, ctx); 1021cc6a4044SJeeja KP 1022d93f8e55SVinod Koul /* Start sinks pipe first */ 1023d93f8e55SVinod Koul if (sink_mconfig->pipe->state != SKL_PIPE_STARTED) { 1024d1730c3dSJeeja KP if (sink_mconfig->pipe->conn_type != 1025d1730c3dSJeeja KP SKL_PIPE_CONN_TYPE_FE) 1026d1730c3dSJeeja KP ret = skl_run_pipe(ctx, 1027d1730c3dSJeeja KP sink_mconfig->pipe); 1028d93f8e55SVinod Koul if (ret) 1029d93f8e55SVinod Koul return ret; 1030d93f8e55SVinod Koul } 1031d93f8e55SVinod Koul } 1032d93f8e55SVinod Koul } 1033d93f8e55SVinod Koul 103410a5439fSguneshwor.o.singh@intel.com if (!sink && next_sink) 10356bd4cf85SJeeja KP return skl_tplg_bind_sinks(next_sink, skl, src_w, src_mconfig); 10368724ff17SJeeja KP 10378724ff17SJeeja KP return 0; 10388724ff17SJeeja KP } 10398724ff17SJeeja KP 1040d93f8e55SVinod Koul /* 1041d93f8e55SVinod Koul * A PGA represents a module in a pipeline. So in the Pre-PMU event of PGA 1042d93f8e55SVinod Koul * we need to do following: 1043d93f8e55SVinod Koul * - Bind to sink pipeline 1044d93f8e55SVinod Koul * Since the sink pipes can be running and we don't get mixer event on 1045d93f8e55SVinod Koul * connect for already running mixer, we need to find the sink pipes 1046d93f8e55SVinod Koul * here and bind to them. This way dynamic connect works. 1047d93f8e55SVinod Koul * - Start sink pipeline, if not running 1048d93f8e55SVinod Koul * - Then run current pipe 1049d93f8e55SVinod Koul */ 1050d93f8e55SVinod Koul static int skl_tplg_pga_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w, 1051d93f8e55SVinod Koul struct skl *skl) 1052d93f8e55SVinod Koul { 10538724ff17SJeeja KP struct skl_module_cfg *src_mconfig; 1054d93f8e55SVinod Koul struct skl_sst *ctx = skl->skl_sst; 1055d93f8e55SVinod Koul int ret = 0; 1056d93f8e55SVinod Koul 10578724ff17SJeeja KP src_mconfig = w->priv; 1058d93f8e55SVinod Koul 1059d93f8e55SVinod Koul /* 1060d93f8e55SVinod Koul * find which sink it is connected to, bind with the sink, 1061d93f8e55SVinod Koul * if sink is not started, start sink pipe first, then start 1062d93f8e55SVinod Koul * this pipe 1063d93f8e55SVinod Koul */ 10646bd4cf85SJeeja KP ret = skl_tplg_bind_sinks(w, skl, w, src_mconfig); 10658724ff17SJeeja KP if (ret) 10668724ff17SJeeja KP return ret; 10678724ff17SJeeja KP 1068d93f8e55SVinod Koul /* Start source pipe last after starting all sinks */ 1069d1730c3dSJeeja KP if (src_mconfig->pipe->conn_type != SKL_PIPE_CONN_TYPE_FE) 1070d1730c3dSJeeja KP return skl_run_pipe(ctx, src_mconfig->pipe); 1071d93f8e55SVinod Koul 1072d93f8e55SVinod Koul return 0; 1073d93f8e55SVinod Koul } 1074d93f8e55SVinod Koul 10758724ff17SJeeja KP static struct snd_soc_dapm_widget *skl_get_src_dsp_widget( 10768724ff17SJeeja KP struct snd_soc_dapm_widget *w, struct skl *skl) 10778724ff17SJeeja KP { 10788724ff17SJeeja KP struct snd_soc_dapm_path *p; 10798724ff17SJeeja KP struct snd_soc_dapm_widget *src_w = NULL; 10808724ff17SJeeja KP struct skl_sst *ctx = skl->skl_sst; 10818724ff17SJeeja KP 1082d93f8e55SVinod Koul snd_soc_dapm_widget_for_each_source_path(w, p) { 10838724ff17SJeeja KP src_w = p->source; 1084d93f8e55SVinod Koul if (!p->connect) 1085d93f8e55SVinod Koul continue; 1086d93f8e55SVinod Koul 10878724ff17SJeeja KP dev_dbg(ctx->dev, "sink widget=%s\n", w->name); 10888724ff17SJeeja KP dev_dbg(ctx->dev, "src widget=%s\n", p->source->name); 1089d93f8e55SVinod Koul 1090d93f8e55SVinod Koul /* 10918724ff17SJeeja KP * here we will check widgets in sink pipelines, so that can 10928724ff17SJeeja KP * be any widgets type and we are only interested if they are 10938724ff17SJeeja KP * ones used for SKL so check that first 1094d93f8e55SVinod Koul */ 10958724ff17SJeeja KP if ((p->source->priv != NULL) && 10968724ff17SJeeja KP is_skl_dsp_widget_type(p->source)) { 10978724ff17SJeeja KP return p->source; 1098d93f8e55SVinod Koul } 1099d93f8e55SVinod Koul } 1100d93f8e55SVinod Koul 11018724ff17SJeeja KP if (src_w != NULL) 11028724ff17SJeeja KP return skl_get_src_dsp_widget(src_w, skl); 1103d93f8e55SVinod Koul 11048724ff17SJeeja KP return NULL; 1105d93f8e55SVinod Koul } 1106d93f8e55SVinod Koul 1107d93f8e55SVinod Koul /* 1108d93f8e55SVinod Koul * in the Post-PMU event of mixer we need to do following: 1109d93f8e55SVinod Koul * - Check if this pipe is running 1110d93f8e55SVinod Koul * - if not, then 1111d93f8e55SVinod Koul * - bind this pipeline to its source pipeline 1112d93f8e55SVinod Koul * if source pipe is already running, this means it is a dynamic 1113d93f8e55SVinod Koul * connection and we need to bind only to that pipe 1114d93f8e55SVinod Koul * - start this pipeline 1115d93f8e55SVinod Koul */ 1116d93f8e55SVinod Koul static int skl_tplg_mixer_dapm_post_pmu_event(struct snd_soc_dapm_widget *w, 1117d93f8e55SVinod Koul struct skl *skl) 1118d93f8e55SVinod Koul { 1119d93f8e55SVinod Koul int ret = 0; 1120d93f8e55SVinod Koul struct snd_soc_dapm_widget *source, *sink; 1121d93f8e55SVinod Koul struct skl_module_cfg *src_mconfig, *sink_mconfig; 1122d93f8e55SVinod Koul struct skl_sst *ctx = skl->skl_sst; 1123d93f8e55SVinod Koul int src_pipe_started = 0; 1124d93f8e55SVinod Koul 1125d93f8e55SVinod Koul sink = w; 1126d93f8e55SVinod Koul sink_mconfig = sink->priv; 1127d93f8e55SVinod Koul 1128d93f8e55SVinod Koul /* 1129d93f8e55SVinod Koul * If source pipe is already started, that means source is driving 1130d93f8e55SVinod Koul * one more sink before this sink got connected, Since source is 1131d93f8e55SVinod Koul * started, bind this sink to source and start this pipe. 1132d93f8e55SVinod Koul */ 11338724ff17SJeeja KP source = skl_get_src_dsp_widget(w, skl); 11348724ff17SJeeja KP if (source != NULL) { 1135d93f8e55SVinod Koul src_mconfig = source->priv; 1136d93f8e55SVinod Koul sink_mconfig = sink->priv; 1137d93f8e55SVinod Koul src_pipe_started = 1; 1138d93f8e55SVinod Koul 1139d93f8e55SVinod Koul /* 11408724ff17SJeeja KP * check pipe state, then no need to bind or start the 11418724ff17SJeeja KP * pipe 1142d93f8e55SVinod Koul */ 1143d93f8e55SVinod Koul if (src_mconfig->pipe->state != SKL_PIPE_STARTED) 1144d93f8e55SVinod Koul src_pipe_started = 0; 1145d93f8e55SVinod Koul } 1146d93f8e55SVinod Koul 1147d93f8e55SVinod Koul if (src_pipe_started) { 1148d93f8e55SVinod Koul ret = skl_bind_modules(ctx, src_mconfig, sink_mconfig); 1149d93f8e55SVinod Koul if (ret) 1150d93f8e55SVinod Koul return ret; 1151d93f8e55SVinod Koul 1152cc6a4044SJeeja KP /* set module params after bind */ 1153cc6a4044SJeeja KP skl_tplg_set_module_bind_params(source, src_mconfig, ctx); 1154cc6a4044SJeeja KP skl_tplg_set_module_bind_params(sink, sink_mconfig, ctx); 1155cc6a4044SJeeja KP 1156d1730c3dSJeeja KP if (sink_mconfig->pipe->conn_type != SKL_PIPE_CONN_TYPE_FE) 1157d93f8e55SVinod Koul ret = skl_run_pipe(ctx, sink_mconfig->pipe); 1158d93f8e55SVinod Koul } 1159d93f8e55SVinod Koul 1160d93f8e55SVinod Koul return ret; 1161d93f8e55SVinod Koul } 1162d93f8e55SVinod Koul 1163d93f8e55SVinod Koul /* 1164d93f8e55SVinod Koul * in the Pre-PMD event of mixer we need to do following: 1165d93f8e55SVinod Koul * - Stop the pipe 1166d93f8e55SVinod Koul * - find the source connections and remove that from dapm_path_list 1167d93f8e55SVinod Koul * - unbind with source pipelines if still connected 1168d93f8e55SVinod Koul */ 1169d93f8e55SVinod Koul static int skl_tplg_mixer_dapm_pre_pmd_event(struct snd_soc_dapm_widget *w, 1170d93f8e55SVinod Koul struct skl *skl) 1171d93f8e55SVinod Koul { 1172d93f8e55SVinod Koul struct skl_module_cfg *src_mconfig, *sink_mconfig; 1173ce1b5551SJeeja KP int ret = 0, i; 1174d93f8e55SVinod Koul struct skl_sst *ctx = skl->skl_sst; 1175d93f8e55SVinod Koul 1176ce1b5551SJeeja KP sink_mconfig = w->priv; 1177d93f8e55SVinod Koul 1178d93f8e55SVinod Koul /* Stop the pipe */ 1179d93f8e55SVinod Koul ret = skl_stop_pipe(ctx, sink_mconfig->pipe); 1180d93f8e55SVinod Koul if (ret) 1181d93f8e55SVinod Koul return ret; 1182d93f8e55SVinod Koul 1183f6fa56e2SRamesh Babu for (i = 0; i < sink_mconfig->module->max_input_pins; i++) { 1184ce1b5551SJeeja KP if (sink_mconfig->m_in_pin[i].pin_state == SKL_PIN_BIND_DONE) { 1185ce1b5551SJeeja KP src_mconfig = sink_mconfig->m_in_pin[i].tgt_mcfg; 1186ce1b5551SJeeja KP if (!src_mconfig) 1187ce1b5551SJeeja KP continue; 1188d93f8e55SVinod Koul 1189ce1b5551SJeeja KP ret = skl_unbind_modules(ctx, 1190ce1b5551SJeeja KP src_mconfig, sink_mconfig); 1191ce1b5551SJeeja KP } 1192d93f8e55SVinod Koul } 1193d93f8e55SVinod Koul 1194d93f8e55SVinod Koul return ret; 1195d93f8e55SVinod Koul } 1196d93f8e55SVinod Koul 1197d93f8e55SVinod Koul /* 1198d93f8e55SVinod Koul * in the Post-PMD event of mixer we need to do following: 1199d93f8e55SVinod Koul * - Free the mcps used 1200d93f8e55SVinod Koul * - Free the mem used 1201d93f8e55SVinod Koul * - Unbind the modules within the pipeline 1202d93f8e55SVinod Koul * - Delete the pipeline (modules are not required to be explicitly 1203d93f8e55SVinod Koul * deleted, pipeline delete is enough here 1204d93f8e55SVinod Koul */ 1205d93f8e55SVinod Koul static int skl_tplg_mixer_dapm_post_pmd_event(struct snd_soc_dapm_widget *w, 1206d93f8e55SVinod Koul struct skl *skl) 1207d93f8e55SVinod Koul { 1208d93f8e55SVinod Koul struct skl_module_cfg *mconfig = w->priv; 1209d93f8e55SVinod Koul struct skl_pipe_module *w_module; 1210d93f8e55SVinod Koul struct skl_module_cfg *src_module = NULL, *dst_module; 1211d93f8e55SVinod Koul struct skl_sst *ctx = skl->skl_sst; 1212d93f8e55SVinod Koul struct skl_pipe *s_pipe = mconfig->pipe; 1213550b349aSDan Carpenter struct skl_module_deferred_bind *modules, *tmp; 1214d93f8e55SVinod Koul 1215260eb73aSDharageswari R if (s_pipe->state == SKL_PIPE_INVALID) 1216260eb73aSDharageswari R return -EINVAL; 1217260eb73aSDharageswari R 1218d93f8e55SVinod Koul skl_tplg_free_pipe_mcps(skl, mconfig); 121965976878SVinod Koul skl_tplg_free_pipe_mem(skl, mconfig); 1220d93f8e55SVinod Koul 1221d93f8e55SVinod Koul list_for_each_entry(w_module, &s_pipe->w_list, node) { 1222b8c722ddSJeeja KP if (list_empty(&skl->bind_list)) 1223b8c722ddSJeeja KP break; 1224b8c722ddSJeeja KP 1225b8c722ddSJeeja KP src_module = w_module->w->priv; 1226b8c722ddSJeeja KP 1227550b349aSDan Carpenter list_for_each_entry_safe(modules, tmp, &skl->bind_list, node) { 1228b8c722ddSJeeja KP /* 1229b8c722ddSJeeja KP * When the destination module is deleted, Unbind the 1230b8c722ddSJeeja KP * modules from deferred bind list. 1231b8c722ddSJeeja KP */ 1232b8c722ddSJeeja KP if (modules->dst == src_module) { 1233b8c722ddSJeeja KP skl_unbind_modules(ctx, modules->src, 1234b8c722ddSJeeja KP modules->dst); 1235b8c722ddSJeeja KP } 1236b8c722ddSJeeja KP 1237b8c722ddSJeeja KP /* 1238b8c722ddSJeeja KP * When the source module is deleted, remove this entry 1239b8c722ddSJeeja KP * from the deferred bind list. 1240b8c722ddSJeeja KP */ 1241b8c722ddSJeeja KP if (modules->src == src_module) { 1242b8c722ddSJeeja KP list_del(&modules->node); 1243b8c722ddSJeeja KP modules->src = NULL; 1244b8c722ddSJeeja KP modules->dst = NULL; 1245b8c722ddSJeeja KP kfree(modules); 1246b8c722ddSJeeja KP } 1247b8c722ddSJeeja KP } 1248b8c722ddSJeeja KP } 1249b8c722ddSJeeja KP 1250b8c722ddSJeeja KP list_for_each_entry(w_module, &s_pipe->w_list, node) { 1251d93f8e55SVinod Koul dst_module = w_module->w->priv; 1252d93f8e55SVinod Koul 1253260eb73aSDharageswari R if (mconfig->m_state >= SKL_MODULE_INIT_DONE) 12547ae3cb15SVinod Koul skl_tplg_free_pipe_mcps(skl, dst_module); 1255d93f8e55SVinod Koul if (src_module == NULL) { 1256d93f8e55SVinod Koul src_module = dst_module; 1257d93f8e55SVinod Koul continue; 1258d93f8e55SVinod Koul } 1259d93f8e55SVinod Koul 12607ca42f5aSGuneshwor Singh skl_unbind_modules(ctx, src_module, dst_module); 1261d93f8e55SVinod Koul src_module = dst_module; 1262d93f8e55SVinod Koul } 1263d93f8e55SVinod Koul 1264547cafa3SVinod Koul skl_delete_pipe(ctx, mconfig->pipe); 1265d93f8e55SVinod Koul 1266473a4d51SJeeja KP list_for_each_entry(w_module, &s_pipe->w_list, node) { 1267473a4d51SJeeja KP src_module = w_module->w->priv; 1268473a4d51SJeeja KP src_module->m_state = SKL_MODULE_UNINIT; 1269473a4d51SJeeja KP } 1270473a4d51SJeeja KP 12716c5768b3SDharageswari R return skl_tplg_unload_pipe_modules(ctx, s_pipe); 1272d93f8e55SVinod Koul } 1273d93f8e55SVinod Koul 1274d93f8e55SVinod Koul /* 1275d93f8e55SVinod Koul * in the Post-PMD event of PGA we need to do following: 1276d93f8e55SVinod Koul * - Free the mcps used 1277d93f8e55SVinod Koul * - Stop the pipeline 1278d93f8e55SVinod Koul * - In source pipe is connected, unbind with source pipelines 1279d93f8e55SVinod Koul */ 1280d93f8e55SVinod Koul static int skl_tplg_pga_dapm_post_pmd_event(struct snd_soc_dapm_widget *w, 1281d93f8e55SVinod Koul struct skl *skl) 1282d93f8e55SVinod Koul { 1283d93f8e55SVinod Koul struct skl_module_cfg *src_mconfig, *sink_mconfig; 1284ce1b5551SJeeja KP int ret = 0, i; 1285d93f8e55SVinod Koul struct skl_sst *ctx = skl->skl_sst; 1286d93f8e55SVinod Koul 1287ce1b5551SJeeja KP src_mconfig = w->priv; 1288d93f8e55SVinod Koul 1289d93f8e55SVinod Koul /* Stop the pipe since this is a mixin module */ 1290d93f8e55SVinod Koul ret = skl_stop_pipe(ctx, src_mconfig->pipe); 1291d93f8e55SVinod Koul if (ret) 1292d93f8e55SVinod Koul return ret; 1293d93f8e55SVinod Koul 1294f6fa56e2SRamesh Babu for (i = 0; i < src_mconfig->module->max_output_pins; i++) { 1295ce1b5551SJeeja KP if (src_mconfig->m_out_pin[i].pin_state == SKL_PIN_BIND_DONE) { 1296ce1b5551SJeeja KP sink_mconfig = src_mconfig->m_out_pin[i].tgt_mcfg; 1297ce1b5551SJeeja KP if (!sink_mconfig) 1298ce1b5551SJeeja KP continue; 1299d93f8e55SVinod Koul /* 1300ce1b5551SJeeja KP * This is a connecter and if path is found that means 1301d93f8e55SVinod Koul * unbind between source and sink has not happened yet 1302d93f8e55SVinod Koul */ 1303ce1b5551SJeeja KP ret = skl_unbind_modules(ctx, src_mconfig, 1304ce1b5551SJeeja KP sink_mconfig); 1305ce1b5551SJeeja KP } 1306d93f8e55SVinod Koul } 1307d93f8e55SVinod Koul 1308d93f8e55SVinod Koul return ret; 1309d93f8e55SVinod Koul } 1310d93f8e55SVinod Koul 1311d93f8e55SVinod Koul /* 1312d93f8e55SVinod Koul * In modelling, we assume there will be ONLY one mixer in a pipeline. If a 1313d93f8e55SVinod Koul * second one is required that is created as another pipe entity. 1314d93f8e55SVinod Koul * The mixer is responsible for pipe management and represent a pipeline 1315d93f8e55SVinod Koul * instance 1316d93f8e55SVinod Koul */ 1317d93f8e55SVinod Koul static int skl_tplg_mixer_event(struct snd_soc_dapm_widget *w, 1318d93f8e55SVinod Koul struct snd_kcontrol *k, int event) 1319d93f8e55SVinod Koul { 1320d93f8e55SVinod Koul struct snd_soc_dapm_context *dapm = w->dapm; 1321d93f8e55SVinod Koul struct skl *skl = get_skl_ctx(dapm->dev); 1322d93f8e55SVinod Koul 1323d93f8e55SVinod Koul switch (event) { 1324d93f8e55SVinod Koul case SND_SOC_DAPM_PRE_PMU: 1325d93f8e55SVinod Koul return skl_tplg_mixer_dapm_pre_pmu_event(w, skl); 1326d93f8e55SVinod Koul 1327d93f8e55SVinod Koul case SND_SOC_DAPM_POST_PMU: 1328d93f8e55SVinod Koul return skl_tplg_mixer_dapm_post_pmu_event(w, skl); 1329d93f8e55SVinod Koul 1330d93f8e55SVinod Koul case SND_SOC_DAPM_PRE_PMD: 1331d93f8e55SVinod Koul return skl_tplg_mixer_dapm_pre_pmd_event(w, skl); 1332d93f8e55SVinod Koul 1333d93f8e55SVinod Koul case SND_SOC_DAPM_POST_PMD: 1334d93f8e55SVinod Koul return skl_tplg_mixer_dapm_post_pmd_event(w, skl); 1335d93f8e55SVinod Koul } 1336d93f8e55SVinod Koul 1337d93f8e55SVinod Koul return 0; 1338d93f8e55SVinod Koul } 1339d93f8e55SVinod Koul 1340d93f8e55SVinod Koul /* 1341d93f8e55SVinod Koul * In modelling, we assumed rest of the modules in pipeline are PGA. But we 1342d93f8e55SVinod Koul * are interested in last PGA (leaf PGA) in a pipeline to disconnect with 1343d93f8e55SVinod Koul * the sink when it is running (two FE to one BE or one FE to two BE) 1344d93f8e55SVinod Koul * scenarios 1345d93f8e55SVinod Koul */ 1346d93f8e55SVinod Koul static int skl_tplg_pga_event(struct snd_soc_dapm_widget *w, 1347d93f8e55SVinod Koul struct snd_kcontrol *k, int event) 1348d93f8e55SVinod Koul 1349d93f8e55SVinod Koul { 1350d93f8e55SVinod Koul struct snd_soc_dapm_context *dapm = w->dapm; 1351d93f8e55SVinod Koul struct skl *skl = get_skl_ctx(dapm->dev); 1352d93f8e55SVinod Koul 1353d93f8e55SVinod Koul switch (event) { 1354d93f8e55SVinod Koul case SND_SOC_DAPM_PRE_PMU: 1355d93f8e55SVinod Koul return skl_tplg_pga_dapm_pre_pmu_event(w, skl); 1356d93f8e55SVinod Koul 1357d93f8e55SVinod Koul case SND_SOC_DAPM_POST_PMD: 1358d93f8e55SVinod Koul return skl_tplg_pga_dapm_post_pmd_event(w, skl); 1359d93f8e55SVinod Koul } 1360d93f8e55SVinod Koul 1361d93f8e55SVinod Koul return 0; 1362d93f8e55SVinod Koul } 1363cfb0a873SVinod Koul 1364140adfbaSJeeja KP static int skl_tplg_tlv_control_get(struct snd_kcontrol *kcontrol, 1365140adfbaSJeeja KP unsigned int __user *data, unsigned int size) 1366140adfbaSJeeja KP { 1367140adfbaSJeeja KP struct soc_bytes_ext *sb = 1368140adfbaSJeeja KP (struct soc_bytes_ext *)kcontrol->private_value; 1369140adfbaSJeeja KP struct skl_algo_data *bc = (struct skl_algo_data *)sb->dobj.private; 13707d9f2911SOmair M Abdullah struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol); 13717d9f2911SOmair M Abdullah struct skl_module_cfg *mconfig = w->priv; 13727d9f2911SOmair M Abdullah struct skl *skl = get_skl_ctx(w->dapm->dev); 13737d9f2911SOmair M Abdullah 13747d9f2911SOmair M Abdullah if (w->power) 13757d9f2911SOmair M Abdullah skl_get_module_params(skl->skl_sst, (u32 *)bc->params, 13760d682104SDharageswari R bc->size, bc->param_id, mconfig); 1377140adfbaSJeeja KP 137841556f68SVinod Koul /* decrement size for TLV header */ 137941556f68SVinod Koul size -= 2 * sizeof(u32); 138041556f68SVinod Koul 138141556f68SVinod Koul /* check size as we don't want to send kernel data */ 138241556f68SVinod Koul if (size > bc->max) 138341556f68SVinod Koul size = bc->max; 138441556f68SVinod Koul 1385140adfbaSJeeja KP if (bc->params) { 1386140adfbaSJeeja KP if (copy_to_user(data, &bc->param_id, sizeof(u32))) 1387140adfbaSJeeja KP return -EFAULT; 1388e8bc3c99SDan Carpenter if (copy_to_user(data + 1, &size, sizeof(u32))) 1389140adfbaSJeeja KP return -EFAULT; 1390e8bc3c99SDan Carpenter if (copy_to_user(data + 2, bc->params, size)) 1391140adfbaSJeeja KP return -EFAULT; 1392140adfbaSJeeja KP } 1393140adfbaSJeeja KP 1394140adfbaSJeeja KP return 0; 1395140adfbaSJeeja KP } 1396140adfbaSJeeja KP 1397140adfbaSJeeja KP #define SKL_PARAM_VENDOR_ID 0xff 1398140adfbaSJeeja KP 1399140adfbaSJeeja KP static int skl_tplg_tlv_control_set(struct snd_kcontrol *kcontrol, 1400140adfbaSJeeja KP const unsigned int __user *data, unsigned int size) 1401140adfbaSJeeja KP { 1402140adfbaSJeeja KP struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol); 1403140adfbaSJeeja KP struct skl_module_cfg *mconfig = w->priv; 1404140adfbaSJeeja KP struct soc_bytes_ext *sb = 1405140adfbaSJeeja KP (struct soc_bytes_ext *)kcontrol->private_value; 1406140adfbaSJeeja KP struct skl_algo_data *ac = (struct skl_algo_data *)sb->dobj.private; 1407140adfbaSJeeja KP struct skl *skl = get_skl_ctx(w->dapm->dev); 1408140adfbaSJeeja KP 1409140adfbaSJeeja KP if (ac->params) { 14100d682104SDharageswari R if (size > ac->max) 14110d682104SDharageswari R return -EINVAL; 14120d682104SDharageswari R 14130d682104SDharageswari R ac->size = size; 1414140adfbaSJeeja KP /* 1415140adfbaSJeeja KP * if the param_is is of type Vendor, firmware expects actual 1416140adfbaSJeeja KP * parameter id and size from the control. 1417140adfbaSJeeja KP */ 1418140adfbaSJeeja KP if (ac->param_id == SKL_PARAM_VENDOR_ID) { 1419140adfbaSJeeja KP if (copy_from_user(ac->params, data, size)) 1420140adfbaSJeeja KP return -EFAULT; 1421140adfbaSJeeja KP } else { 1422140adfbaSJeeja KP if (copy_from_user(ac->params, 142365b4bcb8SAlan data + 2, size)) 1424140adfbaSJeeja KP return -EFAULT; 1425140adfbaSJeeja KP } 1426140adfbaSJeeja KP 1427140adfbaSJeeja KP if (w->power) 1428140adfbaSJeeja KP return skl_set_module_params(skl->skl_sst, 14290d682104SDharageswari R (u32 *)ac->params, ac->size, 1430140adfbaSJeeja KP ac->param_id, mconfig); 1431140adfbaSJeeja KP } 1432140adfbaSJeeja KP 1433140adfbaSJeeja KP return 0; 1434140adfbaSJeeja KP } 1435140adfbaSJeeja KP 14367a1b749bSDharageswari R static int skl_tplg_mic_control_get(struct snd_kcontrol *kcontrol, 14377a1b749bSDharageswari R struct snd_ctl_elem_value *ucontrol) 14387a1b749bSDharageswari R { 14397a1b749bSDharageswari R struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol); 14407a1b749bSDharageswari R struct skl_module_cfg *mconfig = w->priv; 14417a1b749bSDharageswari R struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; 14427a1b749bSDharageswari R u32 ch_type = *((u32 *)ec->dobj.private); 14437a1b749bSDharageswari R 14447a1b749bSDharageswari R if (mconfig->dmic_ch_type == ch_type) 14457a1b749bSDharageswari R ucontrol->value.enumerated.item[0] = 14467a1b749bSDharageswari R mconfig->dmic_ch_combo_index; 14477a1b749bSDharageswari R else 14487a1b749bSDharageswari R ucontrol->value.enumerated.item[0] = 0; 14497a1b749bSDharageswari R 14507a1b749bSDharageswari R return 0; 14517a1b749bSDharageswari R } 14527a1b749bSDharageswari R 14537a1b749bSDharageswari R static int skl_fill_mic_sel_params(struct skl_module_cfg *mconfig, 14547a1b749bSDharageswari R struct skl_mic_sel_config *mic_cfg, struct device *dev) 14557a1b749bSDharageswari R { 14567a1b749bSDharageswari R struct skl_specific_cfg *sp_cfg = &mconfig->formats_config; 14577a1b749bSDharageswari R 14587a1b749bSDharageswari R sp_cfg->caps_size = sizeof(struct skl_mic_sel_config); 14597a1b749bSDharageswari R sp_cfg->set_params = SKL_PARAM_SET; 14607a1b749bSDharageswari R sp_cfg->param_id = 0x00; 14617a1b749bSDharageswari R if (!sp_cfg->caps) { 14627a1b749bSDharageswari R sp_cfg->caps = devm_kzalloc(dev, sp_cfg->caps_size, GFP_KERNEL); 14637a1b749bSDharageswari R if (!sp_cfg->caps) 14647a1b749bSDharageswari R return -ENOMEM; 14657a1b749bSDharageswari R } 14667a1b749bSDharageswari R 14677a1b749bSDharageswari R mic_cfg->mic_switch = SKL_MIC_SEL_SWITCH; 14687a1b749bSDharageswari R mic_cfg->flags = 0; 14697a1b749bSDharageswari R memcpy(sp_cfg->caps, mic_cfg, sp_cfg->caps_size); 14707a1b749bSDharageswari R 14717a1b749bSDharageswari R return 0; 14727a1b749bSDharageswari R } 14737a1b749bSDharageswari R 14747a1b749bSDharageswari R static int skl_tplg_mic_control_set(struct snd_kcontrol *kcontrol, 14757a1b749bSDharageswari R struct snd_ctl_elem_value *ucontrol) 14767a1b749bSDharageswari R { 14777a1b749bSDharageswari R struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol); 14787a1b749bSDharageswari R struct skl_module_cfg *mconfig = w->priv; 14797a1b749bSDharageswari R struct skl_mic_sel_config mic_cfg = {0}; 14807a1b749bSDharageswari R struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; 14817a1b749bSDharageswari R u32 ch_type = *((u32 *)ec->dobj.private); 14827a1b749bSDharageswari R const int *list; 14837a1b749bSDharageswari R u8 in_ch, out_ch, index; 14847a1b749bSDharageswari R 14857a1b749bSDharageswari R mconfig->dmic_ch_type = ch_type; 14867a1b749bSDharageswari R mconfig->dmic_ch_combo_index = ucontrol->value.enumerated.item[0]; 14877a1b749bSDharageswari R 14887a1b749bSDharageswari R /* enum control index 0 is INVALID, so no channels to be set */ 14897a1b749bSDharageswari R if (mconfig->dmic_ch_combo_index == 0) 14907a1b749bSDharageswari R return 0; 14917a1b749bSDharageswari R 14927a1b749bSDharageswari R /* No valid channel selection map for index 0, so offset by 1 */ 14937a1b749bSDharageswari R index = mconfig->dmic_ch_combo_index - 1; 14947a1b749bSDharageswari R 14957a1b749bSDharageswari R switch (ch_type) { 14967a1b749bSDharageswari R case SKL_CH_MONO: 14977a1b749bSDharageswari R if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_mono_list)) 14987a1b749bSDharageswari R return -EINVAL; 14997a1b749bSDharageswari R 15007a1b749bSDharageswari R list = &mic_mono_list[index]; 15017a1b749bSDharageswari R break; 15027a1b749bSDharageswari R 15037a1b749bSDharageswari R case SKL_CH_STEREO: 15047a1b749bSDharageswari R if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_stereo_list)) 15057a1b749bSDharageswari R return -EINVAL; 15067a1b749bSDharageswari R 15077a1b749bSDharageswari R list = mic_stereo_list[index]; 15087a1b749bSDharageswari R break; 15097a1b749bSDharageswari R 15107a1b749bSDharageswari R case SKL_CH_TRIO: 15117a1b749bSDharageswari R if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_trio_list)) 15127a1b749bSDharageswari R return -EINVAL; 15137a1b749bSDharageswari R 15147a1b749bSDharageswari R list = mic_trio_list[index]; 15157a1b749bSDharageswari R break; 15167a1b749bSDharageswari R 15177a1b749bSDharageswari R case SKL_CH_QUATRO: 15187a1b749bSDharageswari R if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_quatro_list)) 15197a1b749bSDharageswari R return -EINVAL; 15207a1b749bSDharageswari R 15217a1b749bSDharageswari R list = mic_quatro_list[index]; 15227a1b749bSDharageswari R break; 15237a1b749bSDharageswari R 15247a1b749bSDharageswari R default: 15257a1b749bSDharageswari R dev_err(w->dapm->dev, 15267a1b749bSDharageswari R "Invalid channel %d for mic_select module\n", 15277a1b749bSDharageswari R ch_type); 15287a1b749bSDharageswari R return -EINVAL; 15297a1b749bSDharageswari R 15307a1b749bSDharageswari R } 15317a1b749bSDharageswari R 15327a1b749bSDharageswari R /* channel type enum map to number of chanels for that type */ 15337a1b749bSDharageswari R for (out_ch = 0; out_ch < ch_type; out_ch++) { 15347a1b749bSDharageswari R in_ch = list[out_ch]; 15357a1b749bSDharageswari R mic_cfg.blob[out_ch][in_ch] = SKL_DEFAULT_MIC_SEL_GAIN; 15367a1b749bSDharageswari R } 15377a1b749bSDharageswari R 15387a1b749bSDharageswari R return skl_fill_mic_sel_params(mconfig, &mic_cfg, w->dapm->dev); 15397a1b749bSDharageswari R } 15407a1b749bSDharageswari R 1541cfb0a873SVinod Koul /* 15428871dcb9SJeeja KP * Fill the dma id for host and link. In case of passthrough 15438871dcb9SJeeja KP * pipeline, this will both host and link in the same 15448871dcb9SJeeja KP * pipeline, so need to copy the link and host based on dev_type 15458871dcb9SJeeja KP */ 15468871dcb9SJeeja KP static void skl_tplg_fill_dma_id(struct skl_module_cfg *mcfg, 15478871dcb9SJeeja KP struct skl_pipe_params *params) 15488871dcb9SJeeja KP { 15498871dcb9SJeeja KP struct skl_pipe *pipe = mcfg->pipe; 15508871dcb9SJeeja KP 15518871dcb9SJeeja KP if (pipe->passthru) { 15528871dcb9SJeeja KP switch (mcfg->dev_type) { 15538871dcb9SJeeja KP case SKL_DEVICE_HDALINK: 15548871dcb9SJeeja KP pipe->p_params->link_dma_id = params->link_dma_id; 155512c3be0eSJeeja KP pipe->p_params->link_index = params->link_index; 15567f975a38SJeeja KP pipe->p_params->link_bps = params->link_bps; 15578871dcb9SJeeja KP break; 15588871dcb9SJeeja KP 15598871dcb9SJeeja KP case SKL_DEVICE_HDAHOST: 15608871dcb9SJeeja KP pipe->p_params->host_dma_id = params->host_dma_id; 15617f975a38SJeeja KP pipe->p_params->host_bps = params->host_bps; 15628871dcb9SJeeja KP break; 15638871dcb9SJeeja KP 15648871dcb9SJeeja KP default: 15658871dcb9SJeeja KP break; 15668871dcb9SJeeja KP } 15678871dcb9SJeeja KP pipe->p_params->s_fmt = params->s_fmt; 15688871dcb9SJeeja KP pipe->p_params->ch = params->ch; 15698871dcb9SJeeja KP pipe->p_params->s_freq = params->s_freq; 15708871dcb9SJeeja KP pipe->p_params->stream = params->stream; 157112c3be0eSJeeja KP pipe->p_params->format = params->format; 15728871dcb9SJeeja KP 15738871dcb9SJeeja KP } else { 15748871dcb9SJeeja KP memcpy(pipe->p_params, params, sizeof(*params)); 15758871dcb9SJeeja KP } 15768871dcb9SJeeja KP } 15778871dcb9SJeeja KP 15788871dcb9SJeeja KP /* 1579cfb0a873SVinod Koul * The FE params are passed by hw_params of the DAI. 1580cfb0a873SVinod Koul * On hw_params, the params are stored in Gateway module of the FE and we 1581cfb0a873SVinod Koul * need to calculate the format in DSP module configuration, that 1582cfb0a873SVinod Koul * conversion is done here 1583cfb0a873SVinod Koul */ 1584cfb0a873SVinod Koul int skl_tplg_update_pipe_params(struct device *dev, 1585cfb0a873SVinod Koul struct skl_module_cfg *mconfig, 1586cfb0a873SVinod Koul struct skl_pipe_params *params) 1587cfb0a873SVinod Koul { 1588f6fa56e2SRamesh Babu struct skl_module_res *res = &mconfig->module->resources[0]; 1589f6fa56e2SRamesh Babu struct skl *skl = get_skl_ctx(dev); 1590cfb0a873SVinod Koul struct skl_module_fmt *format = NULL; 1591f6fa56e2SRamesh Babu u8 cfg_idx = mconfig->pipe->cur_config_idx; 1592cfb0a873SVinod Koul 15938871dcb9SJeeja KP skl_tplg_fill_dma_id(mconfig, params); 1594f6fa56e2SRamesh Babu mconfig->fmt_idx = mconfig->mod_cfg[cfg_idx].fmt_idx; 1595f6fa56e2SRamesh Babu mconfig->res_idx = mconfig->mod_cfg[cfg_idx].res_idx; 1596f6fa56e2SRamesh Babu 1597f6fa56e2SRamesh Babu if (skl->nr_modules) 1598f6fa56e2SRamesh Babu return 0; 1599cfb0a873SVinod Koul 1600cfb0a873SVinod Koul if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) 1601f6fa56e2SRamesh Babu format = &mconfig->module->formats[0].inputs[0].fmt; 1602cfb0a873SVinod Koul else 1603f6fa56e2SRamesh Babu format = &mconfig->module->formats[0].outputs[0].fmt; 1604cfb0a873SVinod Koul 1605cfb0a873SVinod Koul /* set the hw_params */ 1606cfb0a873SVinod Koul format->s_freq = params->s_freq; 1607cfb0a873SVinod Koul format->channels = params->ch; 1608cfb0a873SVinod Koul format->valid_bit_depth = skl_get_bit_depth(params->s_fmt); 1609cfb0a873SVinod Koul 1610cfb0a873SVinod Koul /* 1611cfb0a873SVinod Koul * 16 bit is 16 bit container whereas 24 bit is in 32 bit 1612cfb0a873SVinod Koul * container so update bit depth accordingly 1613cfb0a873SVinod Koul */ 1614cfb0a873SVinod Koul switch (format->valid_bit_depth) { 1615cfb0a873SVinod Koul case SKL_DEPTH_16BIT: 1616cfb0a873SVinod Koul format->bit_depth = format->valid_bit_depth; 1617cfb0a873SVinod Koul break; 1618cfb0a873SVinod Koul 1619cfb0a873SVinod Koul case SKL_DEPTH_24BIT: 16206654f39eSJeeja KP case SKL_DEPTH_32BIT: 1621cfb0a873SVinod Koul format->bit_depth = SKL_DEPTH_32BIT; 1622cfb0a873SVinod Koul break; 1623cfb0a873SVinod Koul 1624cfb0a873SVinod Koul default: 1625cfb0a873SVinod Koul dev_err(dev, "Invalid bit depth %x for pipe\n", 1626cfb0a873SVinod Koul format->valid_bit_depth); 1627cfb0a873SVinod Koul return -EINVAL; 1628cfb0a873SVinod Koul } 1629cfb0a873SVinod Koul 1630cfb0a873SVinod Koul if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) { 1631f6fa56e2SRamesh Babu res->ibs = (format->s_freq / 1000) * 1632cfb0a873SVinod Koul (format->channels) * 1633cfb0a873SVinod Koul (format->bit_depth >> 3); 1634cfb0a873SVinod Koul } else { 1635f6fa56e2SRamesh Babu res->obs = (format->s_freq / 1000) * 1636cfb0a873SVinod Koul (format->channels) * 1637cfb0a873SVinod Koul (format->bit_depth >> 3); 1638cfb0a873SVinod Koul } 1639cfb0a873SVinod Koul 1640cfb0a873SVinod Koul return 0; 1641cfb0a873SVinod Koul } 1642cfb0a873SVinod Koul 1643cfb0a873SVinod Koul /* 1644cfb0a873SVinod Koul * Query the module config for the FE DAI 1645cfb0a873SVinod Koul * This is used to find the hw_params set for that DAI and apply to FE 1646cfb0a873SVinod Koul * pipeline 1647cfb0a873SVinod Koul */ 1648cfb0a873SVinod Koul struct skl_module_cfg * 1649cfb0a873SVinod Koul skl_tplg_fe_get_cpr_module(struct snd_soc_dai *dai, int stream) 1650cfb0a873SVinod Koul { 1651cfb0a873SVinod Koul struct snd_soc_dapm_widget *w; 1652cfb0a873SVinod Koul struct snd_soc_dapm_path *p = NULL; 1653cfb0a873SVinod Koul 1654cfb0a873SVinod Koul if (stream == SNDRV_PCM_STREAM_PLAYBACK) { 1655cfb0a873SVinod Koul w = dai->playback_widget; 1656f0900eb2SSubhransu S. Prusty snd_soc_dapm_widget_for_each_sink_path(w, p) { 1657cfb0a873SVinod Koul if (p->connect && p->sink->power && 1658a28f51dbSJeeja KP !is_skl_dsp_widget_type(p->sink)) 1659cfb0a873SVinod Koul continue; 1660cfb0a873SVinod Koul 1661cfb0a873SVinod Koul if (p->sink->priv) { 1662cfb0a873SVinod Koul dev_dbg(dai->dev, "set params for %s\n", 1663cfb0a873SVinod Koul p->sink->name); 1664cfb0a873SVinod Koul return p->sink->priv; 1665cfb0a873SVinod Koul } 1666cfb0a873SVinod Koul } 1667cfb0a873SVinod Koul } else { 1668cfb0a873SVinod Koul w = dai->capture_widget; 1669f0900eb2SSubhransu S. Prusty snd_soc_dapm_widget_for_each_source_path(w, p) { 1670cfb0a873SVinod Koul if (p->connect && p->source->power && 1671a28f51dbSJeeja KP !is_skl_dsp_widget_type(p->source)) 1672cfb0a873SVinod Koul continue; 1673cfb0a873SVinod Koul 1674cfb0a873SVinod Koul if (p->source->priv) { 1675cfb0a873SVinod Koul dev_dbg(dai->dev, "set params for %s\n", 1676cfb0a873SVinod Koul p->source->name); 1677cfb0a873SVinod Koul return p->source->priv; 1678cfb0a873SVinod Koul } 1679cfb0a873SVinod Koul } 1680cfb0a873SVinod Koul } 1681cfb0a873SVinod Koul 1682cfb0a873SVinod Koul return NULL; 1683cfb0a873SVinod Koul } 1684cfb0a873SVinod Koul 1685718a42b5SDharageswari.R static struct skl_module_cfg *skl_get_mconfig_pb_cpr( 1686718a42b5SDharageswari.R struct snd_soc_dai *dai, struct snd_soc_dapm_widget *w) 1687718a42b5SDharageswari.R { 1688718a42b5SDharageswari.R struct snd_soc_dapm_path *p; 1689718a42b5SDharageswari.R struct skl_module_cfg *mconfig = NULL; 1690718a42b5SDharageswari.R 1691718a42b5SDharageswari.R snd_soc_dapm_widget_for_each_source_path(w, p) { 1692718a42b5SDharageswari.R if (w->endpoints[SND_SOC_DAPM_DIR_OUT] > 0) { 1693718a42b5SDharageswari.R if (p->connect && 1694718a42b5SDharageswari.R (p->sink->id == snd_soc_dapm_aif_out) && 1695718a42b5SDharageswari.R p->source->priv) { 1696718a42b5SDharageswari.R mconfig = p->source->priv; 1697718a42b5SDharageswari.R return mconfig; 1698718a42b5SDharageswari.R } 1699718a42b5SDharageswari.R mconfig = skl_get_mconfig_pb_cpr(dai, p->source); 1700718a42b5SDharageswari.R if (mconfig) 1701718a42b5SDharageswari.R return mconfig; 1702718a42b5SDharageswari.R } 1703718a42b5SDharageswari.R } 1704718a42b5SDharageswari.R return mconfig; 1705718a42b5SDharageswari.R } 1706718a42b5SDharageswari.R 1707718a42b5SDharageswari.R static struct skl_module_cfg *skl_get_mconfig_cap_cpr( 1708718a42b5SDharageswari.R struct snd_soc_dai *dai, struct snd_soc_dapm_widget *w) 1709718a42b5SDharageswari.R { 1710718a42b5SDharageswari.R struct snd_soc_dapm_path *p; 1711718a42b5SDharageswari.R struct skl_module_cfg *mconfig = NULL; 1712718a42b5SDharageswari.R 1713718a42b5SDharageswari.R snd_soc_dapm_widget_for_each_sink_path(w, p) { 1714718a42b5SDharageswari.R if (w->endpoints[SND_SOC_DAPM_DIR_IN] > 0) { 1715718a42b5SDharageswari.R if (p->connect && 1716718a42b5SDharageswari.R (p->source->id == snd_soc_dapm_aif_in) && 1717718a42b5SDharageswari.R p->sink->priv) { 1718718a42b5SDharageswari.R mconfig = p->sink->priv; 1719718a42b5SDharageswari.R return mconfig; 1720718a42b5SDharageswari.R } 1721718a42b5SDharageswari.R mconfig = skl_get_mconfig_cap_cpr(dai, p->sink); 1722718a42b5SDharageswari.R if (mconfig) 1723718a42b5SDharageswari.R return mconfig; 1724718a42b5SDharageswari.R } 1725718a42b5SDharageswari.R } 1726718a42b5SDharageswari.R return mconfig; 1727718a42b5SDharageswari.R } 1728718a42b5SDharageswari.R 1729718a42b5SDharageswari.R struct skl_module_cfg * 1730718a42b5SDharageswari.R skl_tplg_be_get_cpr_module(struct snd_soc_dai *dai, int stream) 1731718a42b5SDharageswari.R { 1732718a42b5SDharageswari.R struct snd_soc_dapm_widget *w; 1733718a42b5SDharageswari.R struct skl_module_cfg *mconfig; 1734718a42b5SDharageswari.R 1735718a42b5SDharageswari.R if (stream == SNDRV_PCM_STREAM_PLAYBACK) { 1736718a42b5SDharageswari.R w = dai->playback_widget; 1737718a42b5SDharageswari.R mconfig = skl_get_mconfig_pb_cpr(dai, w); 1738718a42b5SDharageswari.R } else { 1739718a42b5SDharageswari.R w = dai->capture_widget; 1740718a42b5SDharageswari.R mconfig = skl_get_mconfig_cap_cpr(dai, w); 1741718a42b5SDharageswari.R } 1742718a42b5SDharageswari.R return mconfig; 1743718a42b5SDharageswari.R } 1744718a42b5SDharageswari.R 1745cfb0a873SVinod Koul static u8 skl_tplg_be_link_type(int dev_type) 1746cfb0a873SVinod Koul { 1747cfb0a873SVinod Koul int ret; 1748cfb0a873SVinod Koul 1749cfb0a873SVinod Koul switch (dev_type) { 1750cfb0a873SVinod Koul case SKL_DEVICE_BT: 1751cfb0a873SVinod Koul ret = NHLT_LINK_SSP; 1752cfb0a873SVinod Koul break; 1753cfb0a873SVinod Koul 1754cfb0a873SVinod Koul case SKL_DEVICE_DMIC: 1755cfb0a873SVinod Koul ret = NHLT_LINK_DMIC; 1756cfb0a873SVinod Koul break; 1757cfb0a873SVinod Koul 1758cfb0a873SVinod Koul case SKL_DEVICE_I2S: 1759cfb0a873SVinod Koul ret = NHLT_LINK_SSP; 1760cfb0a873SVinod Koul break; 1761cfb0a873SVinod Koul 1762cfb0a873SVinod Koul case SKL_DEVICE_HDALINK: 1763cfb0a873SVinod Koul ret = NHLT_LINK_HDA; 1764cfb0a873SVinod Koul break; 1765cfb0a873SVinod Koul 1766cfb0a873SVinod Koul default: 1767cfb0a873SVinod Koul ret = NHLT_LINK_INVALID; 1768cfb0a873SVinod Koul break; 1769cfb0a873SVinod Koul } 1770cfb0a873SVinod Koul 1771cfb0a873SVinod Koul return ret; 1772cfb0a873SVinod Koul } 1773cfb0a873SVinod Koul 1774cfb0a873SVinod Koul /* 1775cfb0a873SVinod Koul * Fill the BE gateway parameters 1776cfb0a873SVinod Koul * The BE gateway expects a blob of parameters which are kept in the ACPI 1777cfb0a873SVinod Koul * NHLT blob, so query the blob for interface type (i2s/pdm) and instance. 1778cfb0a873SVinod Koul * The port can have multiple settings so pick based on the PCM 1779cfb0a873SVinod Koul * parameters 1780cfb0a873SVinod Koul */ 1781cfb0a873SVinod Koul static int skl_tplg_be_fill_pipe_params(struct snd_soc_dai *dai, 1782cfb0a873SVinod Koul struct skl_module_cfg *mconfig, 1783cfb0a873SVinod Koul struct skl_pipe_params *params) 1784cfb0a873SVinod Koul { 1785cfb0a873SVinod Koul struct nhlt_specific_cfg *cfg; 1786cfb0a873SVinod Koul struct skl *skl = get_skl_ctx(dai->dev); 1787cfb0a873SVinod Koul int link_type = skl_tplg_be_link_type(mconfig->dev_type); 1788db2f586bSSenthilnathan Veppur u8 dev_type = skl_tplg_be_dev_type(mconfig->dev_type); 1789cfb0a873SVinod Koul 17908871dcb9SJeeja KP skl_tplg_fill_dma_id(mconfig, params); 1791cfb0a873SVinod Koul 1792b30c275eSJeeja KP if (link_type == NHLT_LINK_HDA) 1793b30c275eSJeeja KP return 0; 1794b30c275eSJeeja KP 1795cfb0a873SVinod Koul /* update the blob based on virtual bus_id*/ 1796cfb0a873SVinod Koul cfg = skl_get_ep_blob(skl, mconfig->vbus_id, link_type, 1797cfb0a873SVinod Koul params->s_fmt, params->ch, 1798db2f586bSSenthilnathan Veppur params->s_freq, params->stream, 1799db2f586bSSenthilnathan Veppur dev_type); 1800cfb0a873SVinod Koul if (cfg) { 1801cfb0a873SVinod Koul mconfig->formats_config.caps_size = cfg->size; 1802bc03281aSJeeja KP mconfig->formats_config.caps = (u32 *) &cfg->caps; 1803cfb0a873SVinod Koul } else { 1804cfb0a873SVinod Koul dev_err(dai->dev, "Blob NULL for id %x type %d dirn %d\n", 1805cfb0a873SVinod Koul mconfig->vbus_id, link_type, 1806cfb0a873SVinod Koul params->stream); 1807cfb0a873SVinod Koul dev_err(dai->dev, "PCM: ch %d, freq %d, fmt %d\n", 1808cfb0a873SVinod Koul params->ch, params->s_freq, params->s_fmt); 1809cfb0a873SVinod Koul return -EINVAL; 1810cfb0a873SVinod Koul } 1811cfb0a873SVinod Koul 1812cfb0a873SVinod Koul return 0; 1813cfb0a873SVinod Koul } 1814cfb0a873SVinod Koul 1815cfb0a873SVinod Koul static int skl_tplg_be_set_src_pipe_params(struct snd_soc_dai *dai, 1816cfb0a873SVinod Koul struct snd_soc_dapm_widget *w, 1817cfb0a873SVinod Koul struct skl_pipe_params *params) 1818cfb0a873SVinod Koul { 1819cfb0a873SVinod Koul struct snd_soc_dapm_path *p; 18204d8adccbSSubhransu S. Prusty int ret = -EIO; 1821cfb0a873SVinod Koul 1822f0900eb2SSubhransu S. Prusty snd_soc_dapm_widget_for_each_source_path(w, p) { 1823cfb0a873SVinod Koul if (p->connect && is_skl_dsp_widget_type(p->source) && 1824cfb0a873SVinod Koul p->source->priv) { 1825cfb0a873SVinod Koul 18269a03cb49SJeeja KP ret = skl_tplg_be_fill_pipe_params(dai, 18279a03cb49SJeeja KP p->source->priv, params); 18284d8adccbSSubhransu S. Prusty if (ret < 0) 18294d8adccbSSubhransu S. Prusty return ret; 1830cfb0a873SVinod Koul } else { 18319a03cb49SJeeja KP ret = skl_tplg_be_set_src_pipe_params(dai, 18329a03cb49SJeeja KP p->source, params); 18334d8adccbSSubhransu S. Prusty if (ret < 0) 18344d8adccbSSubhransu S. Prusty return ret; 1835cfb0a873SVinod Koul } 1836cfb0a873SVinod Koul } 1837cfb0a873SVinod Koul 18384d8adccbSSubhransu S. Prusty return ret; 1839cfb0a873SVinod Koul } 1840cfb0a873SVinod Koul 1841cfb0a873SVinod Koul static int skl_tplg_be_set_sink_pipe_params(struct snd_soc_dai *dai, 1842cfb0a873SVinod Koul struct snd_soc_dapm_widget *w, struct skl_pipe_params *params) 1843cfb0a873SVinod Koul { 1844cfb0a873SVinod Koul struct snd_soc_dapm_path *p = NULL; 18454d8adccbSSubhransu S. Prusty int ret = -EIO; 1846cfb0a873SVinod Koul 1847f0900eb2SSubhransu S. Prusty snd_soc_dapm_widget_for_each_sink_path(w, p) { 1848cfb0a873SVinod Koul if (p->connect && is_skl_dsp_widget_type(p->sink) && 1849cfb0a873SVinod Koul p->sink->priv) { 1850cfb0a873SVinod Koul 18519a03cb49SJeeja KP ret = skl_tplg_be_fill_pipe_params(dai, 18529a03cb49SJeeja KP p->sink->priv, params); 18534d8adccbSSubhransu S. Prusty if (ret < 0) 18544d8adccbSSubhransu S. Prusty return ret; 18554d8adccbSSubhransu S. Prusty } else { 18564d8adccbSSubhransu S. Prusty ret = skl_tplg_be_set_sink_pipe_params( 1857cfb0a873SVinod Koul dai, p->sink, params); 18584d8adccbSSubhransu S. Prusty if (ret < 0) 18594d8adccbSSubhransu S. Prusty return ret; 1860cfb0a873SVinod Koul } 1861cfb0a873SVinod Koul } 1862cfb0a873SVinod Koul 18634d8adccbSSubhransu S. Prusty return ret; 1864cfb0a873SVinod Koul } 1865cfb0a873SVinod Koul 1866cfb0a873SVinod Koul /* 1867cfb0a873SVinod Koul * BE hw_params can be a source parameters (capture) or sink parameters 1868cfb0a873SVinod Koul * (playback). Based on sink and source we need to either find the source 1869cfb0a873SVinod Koul * list or the sink list and set the pipeline parameters 1870cfb0a873SVinod Koul */ 1871cfb0a873SVinod Koul int skl_tplg_be_update_params(struct snd_soc_dai *dai, 1872cfb0a873SVinod Koul struct skl_pipe_params *params) 1873cfb0a873SVinod Koul { 1874cfb0a873SVinod Koul struct snd_soc_dapm_widget *w; 1875cfb0a873SVinod Koul 1876cfb0a873SVinod Koul if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) { 1877cfb0a873SVinod Koul w = dai->playback_widget; 1878cfb0a873SVinod Koul 1879cfb0a873SVinod Koul return skl_tplg_be_set_src_pipe_params(dai, w, params); 1880cfb0a873SVinod Koul 1881cfb0a873SVinod Koul } else { 1882cfb0a873SVinod Koul w = dai->capture_widget; 1883cfb0a873SVinod Koul 1884cfb0a873SVinod Koul return skl_tplg_be_set_sink_pipe_params(dai, w, params); 1885cfb0a873SVinod Koul } 1886cfb0a873SVinod Koul 1887cfb0a873SVinod Koul return 0; 1888cfb0a873SVinod Koul } 18893af36706SVinod Koul 18903af36706SVinod Koul static const struct snd_soc_tplg_widget_events skl_tplg_widget_ops[] = { 18913af36706SVinod Koul {SKL_MIXER_EVENT, skl_tplg_mixer_event}, 18929a1e3507SVinod Koul {SKL_VMIXER_EVENT, skl_tplg_mixer_event}, 18933af36706SVinod Koul {SKL_PGA_EVENT, skl_tplg_pga_event}, 18943af36706SVinod Koul }; 18953af36706SVinod Koul 1896140adfbaSJeeja KP static const struct snd_soc_tplg_bytes_ext_ops skl_tlv_ops[] = { 1897140adfbaSJeeja KP {SKL_CONTROL_TYPE_BYTE_TLV, skl_tplg_tlv_control_get, 1898140adfbaSJeeja KP skl_tplg_tlv_control_set}, 1899140adfbaSJeeja KP }; 1900140adfbaSJeeja KP 19017a1b749bSDharageswari R static const struct snd_soc_tplg_kcontrol_ops skl_tplg_kcontrol_ops[] = { 19027a1b749bSDharageswari R { 19037a1b749bSDharageswari R .id = SKL_CONTROL_TYPE_MIC_SELECT, 19047a1b749bSDharageswari R .get = skl_tplg_mic_control_get, 19057a1b749bSDharageswari R .put = skl_tplg_mic_control_set, 19067a1b749bSDharageswari R }, 19077a1b749bSDharageswari R }; 19087a1b749bSDharageswari R 1909f6fa56e2SRamesh Babu static int skl_tplg_fill_pipe_cfg(struct device *dev, 1910f6fa56e2SRamesh Babu struct skl_pipe *pipe, u32 tkn, 1911f6fa56e2SRamesh Babu u32 tkn_val, int conf_idx, int dir) 1912f6fa56e2SRamesh Babu { 1913f6fa56e2SRamesh Babu struct skl_pipe_fmt *fmt; 1914f6fa56e2SRamesh Babu struct skl_path_config *config; 1915f6fa56e2SRamesh Babu 1916f6fa56e2SRamesh Babu switch (dir) { 1917f6fa56e2SRamesh Babu case SKL_DIR_IN: 1918f6fa56e2SRamesh Babu fmt = &pipe->configs[conf_idx].in_fmt; 1919f6fa56e2SRamesh Babu break; 1920f6fa56e2SRamesh Babu 1921f6fa56e2SRamesh Babu case SKL_DIR_OUT: 1922f6fa56e2SRamesh Babu fmt = &pipe->configs[conf_idx].out_fmt; 1923f6fa56e2SRamesh Babu break; 1924f6fa56e2SRamesh Babu 1925f6fa56e2SRamesh Babu default: 1926f6fa56e2SRamesh Babu dev_err(dev, "Invalid direction: %d\n", dir); 1927f6fa56e2SRamesh Babu return -EINVAL; 1928f6fa56e2SRamesh Babu } 1929f6fa56e2SRamesh Babu 1930f6fa56e2SRamesh Babu config = &pipe->configs[conf_idx]; 1931f6fa56e2SRamesh Babu 1932f6fa56e2SRamesh Babu switch (tkn) { 1933f6fa56e2SRamesh Babu case SKL_TKN_U32_CFG_FREQ: 1934f6fa56e2SRamesh Babu fmt->freq = tkn_val; 1935f6fa56e2SRamesh Babu break; 1936f6fa56e2SRamesh Babu 1937f6fa56e2SRamesh Babu case SKL_TKN_U8_CFG_CHAN: 1938f6fa56e2SRamesh Babu fmt->channels = tkn_val; 1939f6fa56e2SRamesh Babu break; 1940f6fa56e2SRamesh Babu 1941f6fa56e2SRamesh Babu case SKL_TKN_U8_CFG_BPS: 1942f6fa56e2SRamesh Babu fmt->bps = tkn_val; 1943f6fa56e2SRamesh Babu break; 1944f6fa56e2SRamesh Babu 1945f6fa56e2SRamesh Babu case SKL_TKN_U32_PATH_MEM_PGS: 1946f6fa56e2SRamesh Babu config->mem_pages = tkn_val; 1947f6fa56e2SRamesh Babu break; 1948f6fa56e2SRamesh Babu 1949f6fa56e2SRamesh Babu default: 1950f6fa56e2SRamesh Babu dev_err(dev, "Invalid token config: %d\n", tkn); 1951f6fa56e2SRamesh Babu return -EINVAL; 1952f6fa56e2SRamesh Babu } 1953f6fa56e2SRamesh Babu 1954f6fa56e2SRamesh Babu return 0; 1955f6fa56e2SRamesh Babu } 1956f6fa56e2SRamesh Babu 19576277e832SShreyas NC static int skl_tplg_fill_pipe_tkn(struct device *dev, 19586277e832SShreyas NC struct skl_pipe *pipe, u32 tkn, 19596277e832SShreyas NC u32 tkn_val) 19603af36706SVinod Koul { 19613af36706SVinod Koul 19626277e832SShreyas NC switch (tkn) { 19636277e832SShreyas NC case SKL_TKN_U32_PIPE_CONN_TYPE: 19646277e832SShreyas NC pipe->conn_type = tkn_val; 19656277e832SShreyas NC break; 19666277e832SShreyas NC 19676277e832SShreyas NC case SKL_TKN_U32_PIPE_PRIORITY: 19686277e832SShreyas NC pipe->pipe_priority = tkn_val; 19696277e832SShreyas NC break; 19706277e832SShreyas NC 19716277e832SShreyas NC case SKL_TKN_U32_PIPE_MEM_PGS: 19726277e832SShreyas NC pipe->memory_pages = tkn_val; 19736277e832SShreyas NC break; 19746277e832SShreyas NC 19758a0cb236SVinod Koul case SKL_TKN_U32_PMODE: 19768a0cb236SVinod Koul pipe->lp_mode = tkn_val; 19778a0cb236SVinod Koul break; 19788a0cb236SVinod Koul 1979f6fa56e2SRamesh Babu case SKL_TKN_U32_PIPE_DIRECTION: 1980f6fa56e2SRamesh Babu pipe->direction = tkn_val; 1981f6fa56e2SRamesh Babu break; 1982f6fa56e2SRamesh Babu 1983f6fa56e2SRamesh Babu case SKL_TKN_U32_NUM_CONFIGS: 1984f6fa56e2SRamesh Babu pipe->nr_cfgs = tkn_val; 1985f6fa56e2SRamesh Babu break; 1986f6fa56e2SRamesh Babu 19876277e832SShreyas NC default: 19886277e832SShreyas NC dev_err(dev, "Token not handled %d\n", tkn); 19896277e832SShreyas NC return -EINVAL; 19903af36706SVinod Koul } 19916277e832SShreyas NC 19926277e832SShreyas NC return 0; 19933af36706SVinod Koul } 19943af36706SVinod Koul 19953af36706SVinod Koul /* 19966277e832SShreyas NC * Add pipeline by parsing the relevant tokens 19976277e832SShreyas NC * Return an existing pipe if the pipe already exists. 19983af36706SVinod Koul */ 19996277e832SShreyas NC static int skl_tplg_add_pipe(struct device *dev, 20006277e832SShreyas NC struct skl_module_cfg *mconfig, struct skl *skl, 20016277e832SShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem) 20023af36706SVinod Koul { 20033af36706SVinod Koul struct skl_pipeline *ppl; 20043af36706SVinod Koul struct skl_pipe *pipe; 20053af36706SVinod Koul struct skl_pipe_params *params; 20063af36706SVinod Koul 20073af36706SVinod Koul list_for_each_entry(ppl, &skl->ppl_list, node) { 20086277e832SShreyas NC if (ppl->pipe->ppl_id == tkn_elem->value) { 20096277e832SShreyas NC mconfig->pipe = ppl->pipe; 2010081dc8abSGuneshwor Singh return -EEXIST; 20116277e832SShreyas NC } 20123af36706SVinod Koul } 20133af36706SVinod Koul 20143af36706SVinod Koul ppl = devm_kzalloc(dev, sizeof(*ppl), GFP_KERNEL); 20153af36706SVinod Koul if (!ppl) 20166277e832SShreyas NC return -ENOMEM; 20173af36706SVinod Koul 20183af36706SVinod Koul pipe = devm_kzalloc(dev, sizeof(*pipe), GFP_KERNEL); 20193af36706SVinod Koul if (!pipe) 20206277e832SShreyas NC return -ENOMEM; 20213af36706SVinod Koul 20223af36706SVinod Koul params = devm_kzalloc(dev, sizeof(*params), GFP_KERNEL); 20233af36706SVinod Koul if (!params) 20246277e832SShreyas NC return -ENOMEM; 20253af36706SVinod Koul 20263af36706SVinod Koul pipe->p_params = params; 20276277e832SShreyas NC pipe->ppl_id = tkn_elem->value; 20283af36706SVinod Koul INIT_LIST_HEAD(&pipe->w_list); 20293af36706SVinod Koul 20303af36706SVinod Koul ppl->pipe = pipe; 20313af36706SVinod Koul list_add(&ppl->node, &skl->ppl_list); 20323af36706SVinod Koul 20336277e832SShreyas NC mconfig->pipe = pipe; 20346277e832SShreyas NC mconfig->pipe->state = SKL_PIPE_INVALID; 20356277e832SShreyas NC 20366277e832SShreyas NC return 0; 20373af36706SVinod Koul } 20383af36706SVinod Koul 2039*22ebd666SSriram Periyasamy static int skl_tplg_get_uuid(struct device *dev, u8 *guid, 2040*22ebd666SSriram Periyasamy struct snd_soc_tplg_vendor_uuid_elem *uuid_tkn) 20416277e832SShreyas NC { 2042*22ebd666SSriram Periyasamy if (uuid_tkn->token == SKL_TKN_UUID) { 2043*22ebd666SSriram Periyasamy memcpy(guid, &uuid_tkn->uuid, 16); 2044*22ebd666SSriram Periyasamy return 0; 2045*22ebd666SSriram Periyasamy } 2046*22ebd666SSriram Periyasamy 2047*22ebd666SSriram Periyasamy dev_err(dev, "Not an UUID token %d\n", uuid_tkn->token); 2048*22ebd666SSriram Periyasamy 2049*22ebd666SSriram Periyasamy return -EINVAL; 2050*22ebd666SSriram Periyasamy } 2051*22ebd666SSriram Periyasamy 2052*22ebd666SSriram Periyasamy static int skl_tplg_fill_pin(struct device *dev, 2053*22ebd666SSriram Periyasamy struct snd_soc_tplg_vendor_value_elem *tkn_elem, 2054*22ebd666SSriram Periyasamy struct skl_module_pin *m_pin, 2055*22ebd666SSriram Periyasamy int pin_index) 2056*22ebd666SSriram Periyasamy { 2057*22ebd666SSriram Periyasamy switch (tkn_elem->token) { 20586277e832SShreyas NC case SKL_TKN_U32_PIN_MOD_ID: 2059*22ebd666SSriram Periyasamy m_pin[pin_index].id.module_id = tkn_elem->value; 20606277e832SShreyas NC break; 20616277e832SShreyas NC 20626277e832SShreyas NC case SKL_TKN_U32_PIN_INST_ID: 2063*22ebd666SSriram Periyasamy m_pin[pin_index].id.instance_id = tkn_elem->value; 20646277e832SShreyas NC break; 20656277e832SShreyas NC 20666277e832SShreyas NC default: 2067*22ebd666SSriram Periyasamy dev_err(dev, "%d Not a pin token\n", tkn_elem->token); 20686277e832SShreyas NC return -EINVAL; 20696277e832SShreyas NC } 20706277e832SShreyas NC 20716277e832SShreyas NC return 0; 20726277e832SShreyas NC } 20736277e832SShreyas NC 20746277e832SShreyas NC /* 20756277e832SShreyas NC * Parse for pin config specific tokens to fill up the 20766277e832SShreyas NC * module private data 20776277e832SShreyas NC */ 20786277e832SShreyas NC static int skl_tplg_fill_pins_info(struct device *dev, 20796277e832SShreyas NC struct skl_module_cfg *mconfig, 20806277e832SShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem, 20816277e832SShreyas NC int dir, int pin_count) 20826277e832SShreyas NC { 20836277e832SShreyas NC int ret; 20846277e832SShreyas NC struct skl_module_pin *m_pin; 20856277e832SShreyas NC 20866277e832SShreyas NC switch (dir) { 20876277e832SShreyas NC case SKL_DIR_IN: 20886277e832SShreyas NC m_pin = mconfig->m_in_pin; 20896277e832SShreyas NC break; 20906277e832SShreyas NC 20916277e832SShreyas NC case SKL_DIR_OUT: 20926277e832SShreyas NC m_pin = mconfig->m_out_pin; 20936277e832SShreyas NC break; 20946277e832SShreyas NC 20956277e832SShreyas NC default: 2096ecd286a9SColin Ian King dev_err(dev, "Invalid direction value\n"); 20976277e832SShreyas NC return -EINVAL; 20986277e832SShreyas NC } 20996277e832SShreyas NC 2100*22ebd666SSriram Periyasamy ret = skl_tplg_fill_pin(dev, tkn_elem, m_pin, pin_count); 21016277e832SShreyas NC if (ret < 0) 21026277e832SShreyas NC return ret; 21036277e832SShreyas NC 21046277e832SShreyas NC m_pin[pin_count].in_use = false; 21056277e832SShreyas NC m_pin[pin_count].pin_state = SKL_PIN_UNBIND; 21066277e832SShreyas NC 21076277e832SShreyas NC return 0; 21086277e832SShreyas NC } 21096277e832SShreyas NC 21106277e832SShreyas NC /* 21116277e832SShreyas NC * Fill up input/output module config format based 21126277e832SShreyas NC * on the direction 21136277e832SShreyas NC */ 21146277e832SShreyas NC static int skl_tplg_fill_fmt(struct device *dev, 2115ca312fdaSShreyas NC struct skl_module_fmt *dst_fmt, 2116ca312fdaSShreyas NC u32 tkn, u32 value) 21176277e832SShreyas NC { 21186277e832SShreyas NC switch (tkn) { 21196277e832SShreyas NC case SKL_TKN_U32_FMT_CH: 21206277e832SShreyas NC dst_fmt->channels = value; 21216277e832SShreyas NC break; 21226277e832SShreyas NC 21236277e832SShreyas NC case SKL_TKN_U32_FMT_FREQ: 21246277e832SShreyas NC dst_fmt->s_freq = value; 21256277e832SShreyas NC break; 21266277e832SShreyas NC 21276277e832SShreyas NC case SKL_TKN_U32_FMT_BIT_DEPTH: 21286277e832SShreyas NC dst_fmt->bit_depth = value; 21296277e832SShreyas NC break; 21306277e832SShreyas NC 21316277e832SShreyas NC case SKL_TKN_U32_FMT_SAMPLE_SIZE: 21326277e832SShreyas NC dst_fmt->valid_bit_depth = value; 21336277e832SShreyas NC break; 21346277e832SShreyas NC 21356277e832SShreyas NC case SKL_TKN_U32_FMT_CH_CONFIG: 21366277e832SShreyas NC dst_fmt->ch_cfg = value; 21376277e832SShreyas NC break; 21386277e832SShreyas NC 21396277e832SShreyas NC case SKL_TKN_U32_FMT_INTERLEAVE: 21406277e832SShreyas NC dst_fmt->interleaving_style = value; 21416277e832SShreyas NC break; 21426277e832SShreyas NC 21436277e832SShreyas NC case SKL_TKN_U32_FMT_SAMPLE_TYPE: 21446277e832SShreyas NC dst_fmt->sample_type = value; 21456277e832SShreyas NC break; 21466277e832SShreyas NC 21476277e832SShreyas NC case SKL_TKN_U32_FMT_CH_MAP: 21486277e832SShreyas NC dst_fmt->ch_map = value; 21496277e832SShreyas NC break; 21506277e832SShreyas NC 21516277e832SShreyas NC default: 2152ecd286a9SColin Ian King dev_err(dev, "Invalid token %d\n", tkn); 21536277e832SShreyas NC return -EINVAL; 21546277e832SShreyas NC } 21556277e832SShreyas NC 21566277e832SShreyas NC return 0; 21576277e832SShreyas NC } 21586277e832SShreyas NC 2159ca312fdaSShreyas NC static int skl_tplg_widget_fill_fmt(struct device *dev, 2160f6fa56e2SRamesh Babu struct skl_module_iface *fmt, 2161ca312fdaSShreyas NC u32 tkn, u32 val, u32 dir, int fmt_idx) 2162ca312fdaSShreyas NC { 2163ca312fdaSShreyas NC struct skl_module_fmt *dst_fmt; 2164ca312fdaSShreyas NC 2165f6fa56e2SRamesh Babu if (!fmt) 2166f6fa56e2SRamesh Babu return -EINVAL; 2167f6fa56e2SRamesh Babu 2168ca312fdaSShreyas NC switch (dir) { 2169ca312fdaSShreyas NC case SKL_DIR_IN: 2170f6fa56e2SRamesh Babu dst_fmt = &fmt->inputs[fmt_idx].fmt; 2171ca312fdaSShreyas NC break; 2172ca312fdaSShreyas NC 2173ca312fdaSShreyas NC case SKL_DIR_OUT: 2174f6fa56e2SRamesh Babu dst_fmt = &fmt->outputs[fmt_idx].fmt; 2175ca312fdaSShreyas NC break; 2176ca312fdaSShreyas NC 2177ca312fdaSShreyas NC default: 2178ca312fdaSShreyas NC dev_err(dev, "Invalid direction: %d\n", dir); 2179ca312fdaSShreyas NC return -EINVAL; 2180ca312fdaSShreyas NC } 2181ca312fdaSShreyas NC 2182ca312fdaSShreyas NC return skl_tplg_fill_fmt(dev, dst_fmt, tkn, val); 2183ca312fdaSShreyas NC } 2184ca312fdaSShreyas NC 21856277e832SShreyas NC static void skl_tplg_fill_pin_dynamic_val( 21866277e832SShreyas NC struct skl_module_pin *mpin, u32 pin_count, u32 value) 21874cd9899fSHardik T Shah { 21884cd9899fSHardik T Shah int i; 21894cd9899fSHardik T Shah 21906277e832SShreyas NC for (i = 0; i < pin_count; i++) 21916277e832SShreyas NC mpin[i].is_dynamic = value; 21924cd9899fSHardik T Shah } 21936277e832SShreyas NC 21946277e832SShreyas NC /* 2195db6ed55dSShreyas NC * Resource table in the manifest has pin specific resources 2196db6ed55dSShreyas NC * like pin and pin buffer size 2197db6ed55dSShreyas NC */ 2198db6ed55dSShreyas NC static int skl_tplg_manifest_pin_res_tkn(struct device *dev, 2199db6ed55dSShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem, 2200db6ed55dSShreyas NC struct skl_module_res *res, int pin_idx, int dir) 2201db6ed55dSShreyas NC { 2202db6ed55dSShreyas NC struct skl_module_pin_resources *m_pin; 2203db6ed55dSShreyas NC 2204db6ed55dSShreyas NC switch (dir) { 2205db6ed55dSShreyas NC case SKL_DIR_IN: 2206db6ed55dSShreyas NC m_pin = &res->input[pin_idx]; 2207db6ed55dSShreyas NC break; 2208db6ed55dSShreyas NC 2209db6ed55dSShreyas NC case SKL_DIR_OUT: 2210db6ed55dSShreyas NC m_pin = &res->output[pin_idx]; 2211db6ed55dSShreyas NC break; 2212db6ed55dSShreyas NC 2213db6ed55dSShreyas NC default: 2214db6ed55dSShreyas NC dev_err(dev, "Invalid pin direction: %d\n", dir); 2215db6ed55dSShreyas NC return -EINVAL; 2216db6ed55dSShreyas NC } 2217db6ed55dSShreyas NC 2218db6ed55dSShreyas NC switch (tkn_elem->token) { 2219db6ed55dSShreyas NC case SKL_TKN_MM_U32_RES_PIN_ID: 2220db6ed55dSShreyas NC m_pin->pin_index = tkn_elem->value; 2221db6ed55dSShreyas NC break; 2222db6ed55dSShreyas NC 2223db6ed55dSShreyas NC case SKL_TKN_MM_U32_PIN_BUF: 2224db6ed55dSShreyas NC m_pin->buf_size = tkn_elem->value; 2225db6ed55dSShreyas NC break; 2226db6ed55dSShreyas NC 2227db6ed55dSShreyas NC default: 2228db6ed55dSShreyas NC dev_err(dev, "Invalid token: %d\n", tkn_elem->token); 2229db6ed55dSShreyas NC return -EINVAL; 2230db6ed55dSShreyas NC } 2231db6ed55dSShreyas NC 2232db6ed55dSShreyas NC return 0; 2233db6ed55dSShreyas NC } 2234db6ed55dSShreyas NC 2235db6ed55dSShreyas NC /* 2236db6ed55dSShreyas NC * Fill module specific resources from the manifest's resource 2237db6ed55dSShreyas NC * table like CPS, DMA size, mem_pages. 2238db6ed55dSShreyas NC */ 2239db6ed55dSShreyas NC static int skl_tplg_fill_res_tkn(struct device *dev, 2240db6ed55dSShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem, 2241db6ed55dSShreyas NC struct skl_module_res *res, 2242db6ed55dSShreyas NC int pin_idx, int dir) 2243db6ed55dSShreyas NC { 2244db6ed55dSShreyas NC int ret, tkn_count = 0; 2245db6ed55dSShreyas NC 2246db6ed55dSShreyas NC if (!res) 2247db6ed55dSShreyas NC return -EINVAL; 2248db6ed55dSShreyas NC 2249db6ed55dSShreyas NC switch (tkn_elem->token) { 2250db6ed55dSShreyas NC case SKL_TKN_MM_U32_CPS: 2251db6ed55dSShreyas NC res->cps = tkn_elem->value; 2252db6ed55dSShreyas NC break; 2253db6ed55dSShreyas NC 2254db6ed55dSShreyas NC case SKL_TKN_MM_U32_DMA_SIZE: 2255db6ed55dSShreyas NC res->dma_buffer_size = tkn_elem->value; 2256db6ed55dSShreyas NC break; 2257db6ed55dSShreyas NC 2258db6ed55dSShreyas NC case SKL_TKN_MM_U32_CPC: 2259db6ed55dSShreyas NC res->cpc = tkn_elem->value; 2260db6ed55dSShreyas NC break; 2261db6ed55dSShreyas NC 2262db6ed55dSShreyas NC case SKL_TKN_U32_MEM_PAGES: 2263db6ed55dSShreyas NC res->is_pages = tkn_elem->value; 2264db6ed55dSShreyas NC break; 2265db6ed55dSShreyas NC 2266db6ed55dSShreyas NC case SKL_TKN_U32_OBS: 2267db6ed55dSShreyas NC res->obs = tkn_elem->value; 2268db6ed55dSShreyas NC break; 2269db6ed55dSShreyas NC 2270db6ed55dSShreyas NC case SKL_TKN_U32_IBS: 2271db6ed55dSShreyas NC res->ibs = tkn_elem->value; 2272db6ed55dSShreyas NC break; 2273db6ed55dSShreyas NC 2274f6fa56e2SRamesh Babu case SKL_TKN_U32_MAX_MCPS: 2275f6fa56e2SRamesh Babu res->cps = tkn_elem->value; 2276f6fa56e2SRamesh Babu break; 2277f6fa56e2SRamesh Babu 2278db6ed55dSShreyas NC case SKL_TKN_MM_U32_RES_PIN_ID: 2279db6ed55dSShreyas NC case SKL_TKN_MM_U32_PIN_BUF: 2280db6ed55dSShreyas NC ret = skl_tplg_manifest_pin_res_tkn(dev, tkn_elem, res, 2281db6ed55dSShreyas NC pin_idx, dir); 2282db6ed55dSShreyas NC if (ret < 0) 2283db6ed55dSShreyas NC return ret; 2284db6ed55dSShreyas NC break; 2285db6ed55dSShreyas NC 2286db6ed55dSShreyas NC default: 2287db6ed55dSShreyas NC dev_err(dev, "Not a res type token: %d", tkn_elem->token); 2288db6ed55dSShreyas NC return -EINVAL; 2289db6ed55dSShreyas NC 2290db6ed55dSShreyas NC } 2291db6ed55dSShreyas NC tkn_count++; 2292db6ed55dSShreyas NC 2293db6ed55dSShreyas NC return tkn_count; 2294db6ed55dSShreyas NC } 2295db6ed55dSShreyas NC 2296db6ed55dSShreyas NC /* 22976277e832SShreyas NC * Parse tokens to fill up the module private data 22986277e832SShreyas NC */ 22996277e832SShreyas NC static int skl_tplg_get_token(struct device *dev, 23006277e832SShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem, 23016277e832SShreyas NC struct skl *skl, struct skl_module_cfg *mconfig) 23026277e832SShreyas NC { 23036277e832SShreyas NC int tkn_count = 0; 23046277e832SShreyas NC int ret; 23056277e832SShreyas NC static int is_pipe_exists; 2306f6fa56e2SRamesh Babu static int pin_index, dir, conf_idx; 2307f6fa56e2SRamesh Babu struct skl_module_iface *iface = NULL; 2308f6fa56e2SRamesh Babu struct skl_module_res *res = NULL; 2309f6fa56e2SRamesh Babu int res_idx = mconfig->res_idx; 2310f6fa56e2SRamesh Babu int fmt_idx = mconfig->fmt_idx; 2311f6fa56e2SRamesh Babu 2312f6fa56e2SRamesh Babu /* 2313f6fa56e2SRamesh Babu * If the manifest structure contains no modules, fill all 2314f6fa56e2SRamesh Babu * the module data to 0th index. 2315f6fa56e2SRamesh Babu * res_idx and fmt_idx are default set to 0. 2316f6fa56e2SRamesh Babu */ 2317f6fa56e2SRamesh Babu if (skl->nr_modules == 0) { 2318f6fa56e2SRamesh Babu res = &mconfig->module->resources[res_idx]; 2319f6fa56e2SRamesh Babu iface = &mconfig->module->formats[fmt_idx]; 2320f6fa56e2SRamesh Babu } 23216277e832SShreyas NC 23226277e832SShreyas NC if (tkn_elem->token > SKL_TKN_MAX) 23236277e832SShreyas NC return -EINVAL; 23246277e832SShreyas NC 23256277e832SShreyas NC switch (tkn_elem->token) { 23266277e832SShreyas NC case SKL_TKN_U8_IN_QUEUE_COUNT: 2327f6fa56e2SRamesh Babu mconfig->module->max_input_pins = tkn_elem->value; 23286277e832SShreyas NC break; 23296277e832SShreyas NC 23306277e832SShreyas NC case SKL_TKN_U8_OUT_QUEUE_COUNT: 2331f6fa56e2SRamesh Babu mconfig->module->max_output_pins = tkn_elem->value; 23326277e832SShreyas NC break; 23336277e832SShreyas NC 23346277e832SShreyas NC case SKL_TKN_U8_DYN_IN_PIN: 23356277e832SShreyas NC if (!mconfig->m_in_pin) 2336f6fa56e2SRamesh Babu mconfig->m_in_pin = devm_kzalloc(dev, MAX_IN_QUEUE * 2337f6fa56e2SRamesh Babu sizeof(*mconfig->m_in_pin), GFP_KERNEL); 2338f6fa56e2SRamesh Babu if (!mconfig->m_in_pin) 23396277e832SShreyas NC return -ENOMEM; 23406277e832SShreyas NC 2341f6fa56e2SRamesh Babu skl_tplg_fill_pin_dynamic_val(mconfig->m_in_pin, MAX_IN_QUEUE, 2342f6fa56e2SRamesh Babu tkn_elem->value); 23436277e832SShreyas NC break; 23446277e832SShreyas NC 23456277e832SShreyas NC case SKL_TKN_U8_DYN_OUT_PIN: 23466277e832SShreyas NC if (!mconfig->m_out_pin) 2347f6fa56e2SRamesh Babu mconfig->m_out_pin = devm_kzalloc(dev, MAX_IN_QUEUE * 2348f6fa56e2SRamesh Babu sizeof(*mconfig->m_in_pin), GFP_KERNEL); 2349f6fa56e2SRamesh Babu if (!mconfig->m_out_pin) 23506277e832SShreyas NC return -ENOMEM; 23516277e832SShreyas NC 2352f6fa56e2SRamesh Babu skl_tplg_fill_pin_dynamic_val(mconfig->m_out_pin, MAX_OUT_QUEUE, 2353f6fa56e2SRamesh Babu tkn_elem->value); 23546277e832SShreyas NC break; 23556277e832SShreyas NC 23566277e832SShreyas NC case SKL_TKN_U8_TIME_SLOT: 23576277e832SShreyas NC mconfig->time_slot = tkn_elem->value; 23586277e832SShreyas NC break; 23596277e832SShreyas NC 23606277e832SShreyas NC case SKL_TKN_U8_CORE_ID: 23616277e832SShreyas NC mconfig->core_id = tkn_elem->value; 23626277e832SShreyas NC 23636277e832SShreyas NC case SKL_TKN_U8_MOD_TYPE: 23646277e832SShreyas NC mconfig->m_type = tkn_elem->value; 23656277e832SShreyas NC break; 23666277e832SShreyas NC 23676277e832SShreyas NC case SKL_TKN_U8_DEV_TYPE: 23686277e832SShreyas NC mconfig->dev_type = tkn_elem->value; 23696277e832SShreyas NC break; 23706277e832SShreyas NC 23716277e832SShreyas NC case SKL_TKN_U8_HW_CONN_TYPE: 23726277e832SShreyas NC mconfig->hw_conn_type = tkn_elem->value; 23736277e832SShreyas NC break; 23746277e832SShreyas NC 23756277e832SShreyas NC case SKL_TKN_U16_MOD_INST_ID: 23766277e832SShreyas NC mconfig->id.instance_id = 23776277e832SShreyas NC tkn_elem->value; 23786277e832SShreyas NC break; 23796277e832SShreyas NC 23806277e832SShreyas NC case SKL_TKN_U32_MEM_PAGES: 23816277e832SShreyas NC case SKL_TKN_U32_MAX_MCPS: 23826277e832SShreyas NC case SKL_TKN_U32_OBS: 23836277e832SShreyas NC case SKL_TKN_U32_IBS: 2384f6fa56e2SRamesh Babu ret = skl_tplg_fill_res_tkn(dev, tkn_elem, res, dir, pin_index); 2385f6fa56e2SRamesh Babu if (ret < 0) 2386f6fa56e2SRamesh Babu return ret; 2387f6fa56e2SRamesh Babu 23886277e832SShreyas NC break; 23896277e832SShreyas NC 23906277e832SShreyas NC case SKL_TKN_U32_VBUS_ID: 23916277e832SShreyas NC mconfig->vbus_id = tkn_elem->value; 23926277e832SShreyas NC break; 23936277e832SShreyas NC 23946277e832SShreyas NC case SKL_TKN_U32_PARAMS_FIXUP: 23956277e832SShreyas NC mconfig->params_fixup = tkn_elem->value; 23966277e832SShreyas NC break; 23976277e832SShreyas NC 23986277e832SShreyas NC case SKL_TKN_U32_CONVERTER: 23996277e832SShreyas NC mconfig->converter = tkn_elem->value; 24006277e832SShreyas NC break; 24016277e832SShreyas NC 2402c0116be3SSubhransu S. Prusty case SKL_TKN_U32_D0I3_CAPS: 24036bd9dcf3SVinod Koul mconfig->d0i3_caps = tkn_elem->value; 24046bd9dcf3SVinod Koul break; 24056bd9dcf3SVinod Koul 24066277e832SShreyas NC case SKL_TKN_U32_PIPE_ID: 24076277e832SShreyas NC ret = skl_tplg_add_pipe(dev, 24086277e832SShreyas NC mconfig, skl, tkn_elem); 24096277e832SShreyas NC 2410081dc8abSGuneshwor Singh if (ret < 0) { 2411081dc8abSGuneshwor Singh if (ret == -EEXIST) { 24126277e832SShreyas NC is_pipe_exists = 1; 2413081dc8abSGuneshwor Singh break; 2414081dc8abSGuneshwor Singh } 2415081dc8abSGuneshwor Singh return is_pipe_exists; 2416081dc8abSGuneshwor Singh } 24176277e832SShreyas NC 24186277e832SShreyas NC break; 24196277e832SShreyas NC 2420f6fa56e2SRamesh Babu case SKL_TKN_U32_PIPE_CONFIG_ID: 2421f6fa56e2SRamesh Babu conf_idx = tkn_elem->value; 2422f6fa56e2SRamesh Babu break; 2423f6fa56e2SRamesh Babu 24246277e832SShreyas NC case SKL_TKN_U32_PIPE_CONN_TYPE: 24256277e832SShreyas NC case SKL_TKN_U32_PIPE_PRIORITY: 24266277e832SShreyas NC case SKL_TKN_U32_PIPE_MEM_PGS: 24278a0cb236SVinod Koul case SKL_TKN_U32_PMODE: 2428f6fa56e2SRamesh Babu case SKL_TKN_U32_PIPE_DIRECTION: 2429f6fa56e2SRamesh Babu case SKL_TKN_U32_NUM_CONFIGS: 24306277e832SShreyas NC if (is_pipe_exists) { 24316277e832SShreyas NC ret = skl_tplg_fill_pipe_tkn(dev, mconfig->pipe, 24326277e832SShreyas NC tkn_elem->token, tkn_elem->value); 24336277e832SShreyas NC if (ret < 0) 24346277e832SShreyas NC return ret; 24356277e832SShreyas NC } 24366277e832SShreyas NC 24376277e832SShreyas NC break; 24386277e832SShreyas NC 2439f6fa56e2SRamesh Babu case SKL_TKN_U32_PATH_MEM_PGS: 2440f6fa56e2SRamesh Babu case SKL_TKN_U32_CFG_FREQ: 2441f6fa56e2SRamesh Babu case SKL_TKN_U8_CFG_CHAN: 2442f6fa56e2SRamesh Babu case SKL_TKN_U8_CFG_BPS: 2443f6fa56e2SRamesh Babu if (mconfig->pipe->nr_cfgs) { 2444f6fa56e2SRamesh Babu ret = skl_tplg_fill_pipe_cfg(dev, mconfig->pipe, 2445f6fa56e2SRamesh Babu tkn_elem->token, tkn_elem->value, 2446f6fa56e2SRamesh Babu conf_idx, dir); 2447f6fa56e2SRamesh Babu if (ret < 0) 2448f6fa56e2SRamesh Babu return ret; 2449f6fa56e2SRamesh Babu } 2450f6fa56e2SRamesh Babu break; 2451f6fa56e2SRamesh Babu 2452f6fa56e2SRamesh Babu case SKL_TKN_CFG_MOD_RES_ID: 2453f6fa56e2SRamesh Babu mconfig->mod_cfg[conf_idx].res_idx = tkn_elem->value; 2454f6fa56e2SRamesh Babu break; 2455f6fa56e2SRamesh Babu 2456f6fa56e2SRamesh Babu case SKL_TKN_CFG_MOD_FMT_ID: 2457f6fa56e2SRamesh Babu mconfig->mod_cfg[conf_idx].fmt_idx = tkn_elem->value; 2458f6fa56e2SRamesh Babu break; 2459f6fa56e2SRamesh Babu 24606277e832SShreyas NC /* 24616277e832SShreyas NC * SKL_TKN_U32_DIR_PIN_COUNT token has the value for both 24626277e832SShreyas NC * direction and the pin count. The first four bits represent 24636277e832SShreyas NC * direction and next four the pin count. 24646277e832SShreyas NC */ 24656277e832SShreyas NC case SKL_TKN_U32_DIR_PIN_COUNT: 24666277e832SShreyas NC dir = tkn_elem->value & SKL_IN_DIR_BIT_MASK; 24676277e832SShreyas NC pin_index = (tkn_elem->value & 24686277e832SShreyas NC SKL_PIN_COUNT_MASK) >> 4; 24696277e832SShreyas NC 24706277e832SShreyas NC break; 24716277e832SShreyas NC 24726277e832SShreyas NC case SKL_TKN_U32_FMT_CH: 24736277e832SShreyas NC case SKL_TKN_U32_FMT_FREQ: 24746277e832SShreyas NC case SKL_TKN_U32_FMT_BIT_DEPTH: 24756277e832SShreyas NC case SKL_TKN_U32_FMT_SAMPLE_SIZE: 24766277e832SShreyas NC case SKL_TKN_U32_FMT_CH_CONFIG: 24776277e832SShreyas NC case SKL_TKN_U32_FMT_INTERLEAVE: 24786277e832SShreyas NC case SKL_TKN_U32_FMT_SAMPLE_TYPE: 24796277e832SShreyas NC case SKL_TKN_U32_FMT_CH_MAP: 2480f6fa56e2SRamesh Babu ret = skl_tplg_widget_fill_fmt(dev, iface, tkn_elem->token, 24816277e832SShreyas NC tkn_elem->value, dir, pin_index); 24826277e832SShreyas NC 24836277e832SShreyas NC if (ret < 0) 24846277e832SShreyas NC return ret; 24856277e832SShreyas NC 24866277e832SShreyas NC break; 24876277e832SShreyas NC 24886277e832SShreyas NC case SKL_TKN_U32_PIN_MOD_ID: 24896277e832SShreyas NC case SKL_TKN_U32_PIN_INST_ID: 24906277e832SShreyas NC ret = skl_tplg_fill_pins_info(dev, 24916277e832SShreyas NC mconfig, tkn_elem, dir, 24926277e832SShreyas NC pin_index); 24936277e832SShreyas NC if (ret < 0) 24946277e832SShreyas NC return ret; 24956277e832SShreyas NC 24966277e832SShreyas NC break; 24976277e832SShreyas NC 24986277e832SShreyas NC case SKL_TKN_U32_CAPS_SIZE: 24996277e832SShreyas NC mconfig->formats_config.caps_size = 25006277e832SShreyas NC tkn_elem->value; 25016277e832SShreyas NC 25026277e832SShreyas NC break; 25036277e832SShreyas NC 2504133e6e5cSShreyas NC case SKL_TKN_U32_CAPS_SET_PARAMS: 2505133e6e5cSShreyas NC mconfig->formats_config.set_params = 2506133e6e5cSShreyas NC tkn_elem->value; 2507133e6e5cSShreyas NC break; 2508133e6e5cSShreyas NC 2509133e6e5cSShreyas NC case SKL_TKN_U32_CAPS_PARAMS_ID: 2510133e6e5cSShreyas NC mconfig->formats_config.param_id = 2511133e6e5cSShreyas NC tkn_elem->value; 2512133e6e5cSShreyas NC break; 2513133e6e5cSShreyas NC 25146277e832SShreyas NC case SKL_TKN_U32_PROC_DOMAIN: 25156277e832SShreyas NC mconfig->domain = 25166277e832SShreyas NC tkn_elem->value; 25176277e832SShreyas NC 25186277e832SShreyas NC break; 25196277e832SShreyas NC 2520939df3adSRamesh Babu case SKL_TKN_U32_DMA_BUF_SIZE: 2521939df3adSRamesh Babu mconfig->dma_buffer_size = tkn_elem->value; 2522939df3adSRamesh Babu break; 2523939df3adSRamesh Babu 25246277e832SShreyas NC case SKL_TKN_U8_IN_PIN_TYPE: 25256277e832SShreyas NC case SKL_TKN_U8_OUT_PIN_TYPE: 25266277e832SShreyas NC case SKL_TKN_U8_CONN_TYPE: 25276277e832SShreyas NC break; 25286277e832SShreyas NC 25296277e832SShreyas NC default: 25306277e832SShreyas NC dev_err(dev, "Token %d not handled\n", 25316277e832SShreyas NC tkn_elem->token); 25326277e832SShreyas NC return -EINVAL; 25336277e832SShreyas NC } 25346277e832SShreyas NC 25356277e832SShreyas NC tkn_count++; 25366277e832SShreyas NC 25376277e832SShreyas NC return tkn_count; 25386277e832SShreyas NC } 25396277e832SShreyas NC 25406277e832SShreyas NC /* 25416277e832SShreyas NC * Parse the vendor array for specific tokens to construct 25426277e832SShreyas NC * module private data 25436277e832SShreyas NC */ 25446277e832SShreyas NC static int skl_tplg_get_tokens(struct device *dev, 25456277e832SShreyas NC char *pvt_data, struct skl *skl, 25466277e832SShreyas NC struct skl_module_cfg *mconfig, int block_size) 25476277e832SShreyas NC { 25486277e832SShreyas NC struct snd_soc_tplg_vendor_array *array; 25496277e832SShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem; 25506277e832SShreyas NC int tkn_count = 0, ret; 25516277e832SShreyas NC int off = 0, tuple_size = 0; 25526277e832SShreyas NC 25536277e832SShreyas NC if (block_size <= 0) 25546277e832SShreyas NC return -EINVAL; 25556277e832SShreyas NC 25566277e832SShreyas NC while (tuple_size < block_size) { 25576277e832SShreyas NC array = (struct snd_soc_tplg_vendor_array *)(pvt_data + off); 25586277e832SShreyas NC 25596277e832SShreyas NC off += array->size; 25606277e832SShreyas NC 25616277e832SShreyas NC switch (array->type) { 25626277e832SShreyas NC case SND_SOC_TPLG_TUPLE_TYPE_STRING: 2563ecd286a9SColin Ian King dev_warn(dev, "no string tokens expected for skl tplg\n"); 25646277e832SShreyas NC continue; 25656277e832SShreyas NC 25666277e832SShreyas NC case SND_SOC_TPLG_TUPLE_TYPE_UUID: 2567*22ebd666SSriram Periyasamy ret = skl_tplg_get_uuid(dev, mconfig->guid, 2568*22ebd666SSriram Periyasamy array->uuid); 25696277e832SShreyas NC if (ret < 0) 25706277e832SShreyas NC return ret; 25716277e832SShreyas NC 25726277e832SShreyas NC tuple_size += sizeof(*array->uuid); 25736277e832SShreyas NC 25746277e832SShreyas NC continue; 25756277e832SShreyas NC 25766277e832SShreyas NC default: 25776277e832SShreyas NC tkn_elem = array->value; 25786277e832SShreyas NC tkn_count = 0; 25796277e832SShreyas NC break; 25806277e832SShreyas NC } 25816277e832SShreyas NC 25826277e832SShreyas NC while (tkn_count <= (array->num_elems - 1)) { 25836277e832SShreyas NC ret = skl_tplg_get_token(dev, tkn_elem, 25846277e832SShreyas NC skl, mconfig); 25856277e832SShreyas NC 25866277e832SShreyas NC if (ret < 0) 25876277e832SShreyas NC return ret; 25886277e832SShreyas NC 25896277e832SShreyas NC tkn_count = tkn_count + ret; 25906277e832SShreyas NC tkn_elem++; 25916277e832SShreyas NC } 25926277e832SShreyas NC 25936277e832SShreyas NC tuple_size += tkn_count * sizeof(*tkn_elem); 25946277e832SShreyas NC } 25956277e832SShreyas NC 2596133e6e5cSShreyas NC return off; 25976277e832SShreyas NC } 25986277e832SShreyas NC 25996277e832SShreyas NC /* 26006277e832SShreyas NC * Every data block is preceded by a descriptor to read the number 26016277e832SShreyas NC * of data blocks, they type of the block and it's size 26026277e832SShreyas NC */ 26036277e832SShreyas NC static int skl_tplg_get_desc_blocks(struct device *dev, 26046277e832SShreyas NC struct snd_soc_tplg_vendor_array *array) 26056277e832SShreyas NC { 26066277e832SShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem; 26076277e832SShreyas NC 26086277e832SShreyas NC tkn_elem = array->value; 26096277e832SShreyas NC 26106277e832SShreyas NC switch (tkn_elem->token) { 26116277e832SShreyas NC case SKL_TKN_U8_NUM_BLOCKS: 26126277e832SShreyas NC case SKL_TKN_U8_BLOCK_TYPE: 26136277e832SShreyas NC case SKL_TKN_U16_BLOCK_SIZE: 26146277e832SShreyas NC return tkn_elem->value; 26156277e832SShreyas NC 26166277e832SShreyas NC default: 2617ecd286a9SColin Ian King dev_err(dev, "Invalid descriptor token %d\n", tkn_elem->token); 26186277e832SShreyas NC break; 26196277e832SShreyas NC } 26206277e832SShreyas NC 26216277e832SShreyas NC return -EINVAL; 26226277e832SShreyas NC } 26236277e832SShreyas NC 26246277e832SShreyas NC /* 26256277e832SShreyas NC * Parse the private data for the token and corresponding value. 26266277e832SShreyas NC * The private data can have multiple data blocks. So, a data block 26276277e832SShreyas NC * is preceded by a descriptor for number of blocks and a descriptor 26286277e832SShreyas NC * for the type and size of the suceeding data block. 26296277e832SShreyas NC */ 26306277e832SShreyas NC static int skl_tplg_get_pvt_data(struct snd_soc_tplg_dapm_widget *tplg_w, 26316277e832SShreyas NC struct skl *skl, struct device *dev, 26326277e832SShreyas NC struct skl_module_cfg *mconfig) 26336277e832SShreyas NC { 26346277e832SShreyas NC struct snd_soc_tplg_vendor_array *array; 26356277e832SShreyas NC int num_blocks, block_size = 0, block_type, off = 0; 26366277e832SShreyas NC char *data; 26376277e832SShreyas NC int ret; 26386277e832SShreyas NC 26396277e832SShreyas NC /* Read the NUM_DATA_BLOCKS descriptor */ 26406277e832SShreyas NC array = (struct snd_soc_tplg_vendor_array *)tplg_w->priv.data; 26416277e832SShreyas NC ret = skl_tplg_get_desc_blocks(dev, array); 26426277e832SShreyas NC if (ret < 0) 26436277e832SShreyas NC return ret; 26446277e832SShreyas NC num_blocks = ret; 26456277e832SShreyas NC 26466277e832SShreyas NC off += array->size; 26476277e832SShreyas NC /* Read the BLOCK_TYPE and BLOCK_SIZE descriptor */ 26486277e832SShreyas NC while (num_blocks > 0) { 2649133e6e5cSShreyas NC array = (struct snd_soc_tplg_vendor_array *) 2650133e6e5cSShreyas NC (tplg_w->priv.data + off); 2651133e6e5cSShreyas NC 26526277e832SShreyas NC ret = skl_tplg_get_desc_blocks(dev, array); 26536277e832SShreyas NC 26546277e832SShreyas NC if (ret < 0) 26556277e832SShreyas NC return ret; 26566277e832SShreyas NC block_type = ret; 26576277e832SShreyas NC off += array->size; 26586277e832SShreyas NC 26596277e832SShreyas NC array = (struct snd_soc_tplg_vendor_array *) 26606277e832SShreyas NC (tplg_w->priv.data + off); 26616277e832SShreyas NC 26626277e832SShreyas NC ret = skl_tplg_get_desc_blocks(dev, array); 26636277e832SShreyas NC 26646277e832SShreyas NC if (ret < 0) 26656277e832SShreyas NC return ret; 26666277e832SShreyas NC block_size = ret; 26676277e832SShreyas NC off += array->size; 26686277e832SShreyas NC 26696277e832SShreyas NC array = (struct snd_soc_tplg_vendor_array *) 26706277e832SShreyas NC (tplg_w->priv.data + off); 26716277e832SShreyas NC 26726277e832SShreyas NC data = (tplg_w->priv.data + off); 26736277e832SShreyas NC 26746277e832SShreyas NC if (block_type == SKL_TYPE_TUPLE) { 26756277e832SShreyas NC ret = skl_tplg_get_tokens(dev, data, 26766277e832SShreyas NC skl, mconfig, block_size); 26776277e832SShreyas NC 26786277e832SShreyas NC if (ret < 0) 26796277e832SShreyas NC return ret; 26806277e832SShreyas NC 26816277e832SShreyas NC --num_blocks; 26826277e832SShreyas NC } else { 26836277e832SShreyas NC if (mconfig->formats_config.caps_size > 0) 26846277e832SShreyas NC memcpy(mconfig->formats_config.caps, data, 26856277e832SShreyas NC mconfig->formats_config.caps_size); 26866277e832SShreyas NC --num_blocks; 2687133e6e5cSShreyas NC ret = mconfig->formats_config.caps_size; 26886277e832SShreyas NC } 2689133e6e5cSShreyas NC off += ret; 26906277e832SShreyas NC } 26916277e832SShreyas NC 26926277e832SShreyas NC return 0; 26934cd9899fSHardik T Shah } 26944cd9899fSHardik T Shah 2695fe3f4442SDharageswari R static void skl_clear_pin_config(struct snd_soc_platform *platform, 2696fe3f4442SDharageswari R struct snd_soc_dapm_widget *w) 2697fe3f4442SDharageswari R { 2698fe3f4442SDharageswari R int i; 2699fe3f4442SDharageswari R struct skl_module_cfg *mconfig; 2700fe3f4442SDharageswari R struct skl_pipe *pipe; 2701fe3f4442SDharageswari R 2702fe3f4442SDharageswari R if (!strncmp(w->dapm->component->name, platform->component.name, 2703fe3f4442SDharageswari R strlen(platform->component.name))) { 2704fe3f4442SDharageswari R mconfig = w->priv; 2705fe3f4442SDharageswari R pipe = mconfig->pipe; 2706f6fa56e2SRamesh Babu for (i = 0; i < mconfig->module->max_input_pins; i++) { 2707fe3f4442SDharageswari R mconfig->m_in_pin[i].in_use = false; 2708fe3f4442SDharageswari R mconfig->m_in_pin[i].pin_state = SKL_PIN_UNBIND; 2709fe3f4442SDharageswari R } 2710f6fa56e2SRamesh Babu for (i = 0; i < mconfig->module->max_output_pins; i++) { 2711fe3f4442SDharageswari R mconfig->m_out_pin[i].in_use = false; 2712fe3f4442SDharageswari R mconfig->m_out_pin[i].pin_state = SKL_PIN_UNBIND; 2713fe3f4442SDharageswari R } 2714fe3f4442SDharageswari R pipe->state = SKL_PIPE_INVALID; 2715fe3f4442SDharageswari R mconfig->m_state = SKL_MODULE_UNINIT; 2716fe3f4442SDharageswari R } 2717fe3f4442SDharageswari R } 2718fe3f4442SDharageswari R 2719fe3f4442SDharageswari R void skl_cleanup_resources(struct skl *skl) 2720fe3f4442SDharageswari R { 2721fe3f4442SDharageswari R struct skl_sst *ctx = skl->skl_sst; 2722fe3f4442SDharageswari R struct snd_soc_platform *soc_platform = skl->platform; 2723fe3f4442SDharageswari R struct snd_soc_dapm_widget *w; 2724fe3f4442SDharageswari R struct snd_soc_card *card; 2725fe3f4442SDharageswari R 2726fe3f4442SDharageswari R if (soc_platform == NULL) 2727fe3f4442SDharageswari R return; 2728fe3f4442SDharageswari R 2729fe3f4442SDharageswari R card = soc_platform->component.card; 2730fe3f4442SDharageswari R if (!card || !card->instantiated) 2731fe3f4442SDharageswari R return; 2732fe3f4442SDharageswari R 2733fe3f4442SDharageswari R skl->resource.mem = 0; 2734fe3f4442SDharageswari R skl->resource.mcps = 0; 2735fe3f4442SDharageswari R 2736fe3f4442SDharageswari R list_for_each_entry(w, &card->widgets, list) { 2737fe3f4442SDharageswari R if (is_skl_dsp_widget_type(w) && (w->priv != NULL)) 2738fe3f4442SDharageswari R skl_clear_pin_config(soc_platform, w); 2739fe3f4442SDharageswari R } 2740fe3f4442SDharageswari R 2741fe3f4442SDharageswari R skl_clear_module_cnt(ctx->dsp); 2742fe3f4442SDharageswari R } 2743fe3f4442SDharageswari R 27443af36706SVinod Koul /* 27453af36706SVinod Koul * Topology core widget load callback 27463af36706SVinod Koul * 27473af36706SVinod Koul * This is used to save the private data for each widget which gives 27483af36706SVinod Koul * information to the driver about module and pipeline parameters which DSP 27493af36706SVinod Koul * FW expects like ids, resource values, formats etc 27503af36706SVinod Koul */ 27513af36706SVinod Koul static int skl_tplg_widget_load(struct snd_soc_component *cmpnt, 27523af36706SVinod Koul struct snd_soc_dapm_widget *w, 27533af36706SVinod Koul struct snd_soc_tplg_dapm_widget *tplg_w) 27543af36706SVinod Koul { 27553af36706SVinod Koul int ret; 27563af36706SVinod Koul struct hdac_ext_bus *ebus = snd_soc_component_get_drvdata(cmpnt); 27573af36706SVinod Koul struct skl *skl = ebus_to_skl(ebus); 27583af36706SVinod Koul struct hdac_bus *bus = ebus_to_hbus(ebus); 27593af36706SVinod Koul struct skl_module_cfg *mconfig; 27603af36706SVinod Koul 27613af36706SVinod Koul if (!tplg_w->priv.size) 27623af36706SVinod Koul goto bind_event; 27633af36706SVinod Koul 27643af36706SVinod Koul mconfig = devm_kzalloc(bus->dev, sizeof(*mconfig), GFP_KERNEL); 27653af36706SVinod Koul 27663af36706SVinod Koul if (!mconfig) 27673af36706SVinod Koul return -ENOMEM; 27683af36706SVinod Koul 2769f6fa56e2SRamesh Babu if (skl->nr_modules == 0) { 2770f6fa56e2SRamesh Babu mconfig->module = devm_kzalloc(bus->dev, 2771f6fa56e2SRamesh Babu sizeof(*mconfig->module), GFP_KERNEL); 2772f6fa56e2SRamesh Babu if (!mconfig->module) 2773f6fa56e2SRamesh Babu return -ENOMEM; 2774f6fa56e2SRamesh Babu } 2775f6fa56e2SRamesh Babu 27763af36706SVinod Koul w->priv = mconfig; 277709305da9SShreyas NC 2778b7c50555SVinod Koul /* 2779b7c50555SVinod Koul * module binary can be loaded later, so set it to query when 2780b7c50555SVinod Koul * module is load for a use case 2781b7c50555SVinod Koul */ 2782b7c50555SVinod Koul mconfig->id.module_id = -1; 27834cd9899fSHardik T Shah 27846277e832SShreyas NC /* Parse private data for tuples */ 27856277e832SShreyas NC ret = skl_tplg_get_pvt_data(tplg_w, skl, bus->dev, mconfig); 27866277e832SShreyas NC if (ret < 0) 27876277e832SShreyas NC return ret; 2788d14700a0SVinod Koul 2789d14700a0SVinod Koul skl_debug_init_module(skl->debugfs, w, mconfig); 2790d14700a0SVinod Koul 27913af36706SVinod Koul bind_event: 27923af36706SVinod Koul if (tplg_w->event_type == 0) { 27933373f716SVinod Koul dev_dbg(bus->dev, "ASoC: No event handler required\n"); 27943af36706SVinod Koul return 0; 27953af36706SVinod Koul } 27963af36706SVinod Koul 27973af36706SVinod Koul ret = snd_soc_tplg_widget_bind_event(w, skl_tplg_widget_ops, 2798b663a8c5SJeeja KP ARRAY_SIZE(skl_tplg_widget_ops), 2799b663a8c5SJeeja KP tplg_w->event_type); 28003af36706SVinod Koul 28013af36706SVinod Koul if (ret) { 28023af36706SVinod Koul dev_err(bus->dev, "%s: No matching event handlers found for %d\n", 28033af36706SVinod Koul __func__, tplg_w->event_type); 28043af36706SVinod Koul return -EINVAL; 28053af36706SVinod Koul } 28063af36706SVinod Koul 28073af36706SVinod Koul return 0; 28083af36706SVinod Koul } 28093af36706SVinod Koul 2810140adfbaSJeeja KP static int skl_init_algo_data(struct device *dev, struct soc_bytes_ext *be, 2811140adfbaSJeeja KP struct snd_soc_tplg_bytes_control *bc) 2812140adfbaSJeeja KP { 2813140adfbaSJeeja KP struct skl_algo_data *ac; 2814140adfbaSJeeja KP struct skl_dfw_algo_data *dfw_ac = 2815140adfbaSJeeja KP (struct skl_dfw_algo_data *)bc->priv.data; 2816140adfbaSJeeja KP 2817140adfbaSJeeja KP ac = devm_kzalloc(dev, sizeof(*ac), GFP_KERNEL); 2818140adfbaSJeeja KP if (!ac) 2819140adfbaSJeeja KP return -ENOMEM; 2820140adfbaSJeeja KP 2821140adfbaSJeeja KP /* Fill private data */ 2822140adfbaSJeeja KP ac->max = dfw_ac->max; 2823140adfbaSJeeja KP ac->param_id = dfw_ac->param_id; 2824140adfbaSJeeja KP ac->set_params = dfw_ac->set_params; 28250d682104SDharageswari R ac->size = dfw_ac->max; 2826140adfbaSJeeja KP 2827140adfbaSJeeja KP if (ac->max) { 2828140adfbaSJeeja KP ac->params = (char *) devm_kzalloc(dev, ac->max, GFP_KERNEL); 2829140adfbaSJeeja KP if (!ac->params) 2830140adfbaSJeeja KP return -ENOMEM; 2831140adfbaSJeeja KP 2832140adfbaSJeeja KP memcpy(ac->params, dfw_ac->params, ac->max); 2833140adfbaSJeeja KP } 2834140adfbaSJeeja KP 2835140adfbaSJeeja KP be->dobj.private = ac; 2836140adfbaSJeeja KP return 0; 2837140adfbaSJeeja KP } 2838140adfbaSJeeja KP 28397a1b749bSDharageswari R static int skl_init_enum_data(struct device *dev, struct soc_enum *se, 28407a1b749bSDharageswari R struct snd_soc_tplg_enum_control *ec) 28417a1b749bSDharageswari R { 28427a1b749bSDharageswari R 28437a1b749bSDharageswari R void *data; 28447a1b749bSDharageswari R 28457a1b749bSDharageswari R if (ec->priv.size) { 28467a1b749bSDharageswari R data = devm_kzalloc(dev, sizeof(ec->priv.size), GFP_KERNEL); 28477a1b749bSDharageswari R if (!data) 28487a1b749bSDharageswari R return -ENOMEM; 28497a1b749bSDharageswari R memcpy(data, ec->priv.data, ec->priv.size); 28507a1b749bSDharageswari R se->dobj.private = data; 28517a1b749bSDharageswari R } 28527a1b749bSDharageswari R 28537a1b749bSDharageswari R return 0; 28547a1b749bSDharageswari R 28557a1b749bSDharageswari R } 28567a1b749bSDharageswari R 2857140adfbaSJeeja KP static int skl_tplg_control_load(struct snd_soc_component *cmpnt, 2858140adfbaSJeeja KP struct snd_kcontrol_new *kctl, 2859140adfbaSJeeja KP struct snd_soc_tplg_ctl_hdr *hdr) 2860140adfbaSJeeja KP { 2861140adfbaSJeeja KP struct soc_bytes_ext *sb; 2862140adfbaSJeeja KP struct snd_soc_tplg_bytes_control *tplg_bc; 28637a1b749bSDharageswari R struct snd_soc_tplg_enum_control *tplg_ec; 2864140adfbaSJeeja KP struct hdac_ext_bus *ebus = snd_soc_component_get_drvdata(cmpnt); 2865140adfbaSJeeja KP struct hdac_bus *bus = ebus_to_hbus(ebus); 28667a1b749bSDharageswari R struct soc_enum *se; 2867140adfbaSJeeja KP 2868140adfbaSJeeja KP switch (hdr->ops.info) { 2869140adfbaSJeeja KP case SND_SOC_TPLG_CTL_BYTES: 2870140adfbaSJeeja KP tplg_bc = container_of(hdr, 2871140adfbaSJeeja KP struct snd_soc_tplg_bytes_control, hdr); 2872140adfbaSJeeja KP if (kctl->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { 2873140adfbaSJeeja KP sb = (struct soc_bytes_ext *)kctl->private_value; 2874140adfbaSJeeja KP if (tplg_bc->priv.size) 2875140adfbaSJeeja KP return skl_init_algo_data( 2876140adfbaSJeeja KP bus->dev, sb, tplg_bc); 2877140adfbaSJeeja KP } 2878140adfbaSJeeja KP break; 2879140adfbaSJeeja KP 28807a1b749bSDharageswari R case SND_SOC_TPLG_CTL_ENUM: 28817a1b749bSDharageswari R tplg_ec = container_of(hdr, 28827a1b749bSDharageswari R struct snd_soc_tplg_enum_control, hdr); 28837a1b749bSDharageswari R if (kctl->access & SNDRV_CTL_ELEM_ACCESS_READWRITE) { 28847a1b749bSDharageswari R se = (struct soc_enum *)kctl->private_value; 28857a1b749bSDharageswari R if (tplg_ec->priv.size) 28867a1b749bSDharageswari R return skl_init_enum_data(bus->dev, se, 28877a1b749bSDharageswari R tplg_ec); 28887a1b749bSDharageswari R } 28897a1b749bSDharageswari R break; 28907a1b749bSDharageswari R 2891140adfbaSJeeja KP default: 2892140adfbaSJeeja KP dev_warn(bus->dev, "Control load not supported %d:%d:%d\n", 2893140adfbaSJeeja KP hdr->ops.get, hdr->ops.put, hdr->ops.info); 2894140adfbaSJeeja KP break; 2895140adfbaSJeeja KP } 2896140adfbaSJeeja KP 2897140adfbaSJeeja KP return 0; 2898140adfbaSJeeja KP } 2899140adfbaSJeeja KP 2900541070ceSShreyas NC static int skl_tplg_fill_str_mfest_tkn(struct device *dev, 2901541070ceSShreyas NC struct snd_soc_tplg_vendor_string_elem *str_elem, 2902eee0e16fSJeeja KP struct skl *skl) 2903541070ceSShreyas NC { 2904541070ceSShreyas NC int tkn_count = 0; 2905541070ceSShreyas NC static int ref_count; 2906541070ceSShreyas NC 2907541070ceSShreyas NC switch (str_elem->token) { 2908541070ceSShreyas NC case SKL_TKN_STR_LIB_NAME: 2909eee0e16fSJeeja KP if (ref_count > skl->skl_sst->lib_count - 1) { 2910541070ceSShreyas NC ref_count = 0; 2911541070ceSShreyas NC return -EINVAL; 2912541070ceSShreyas NC } 2913541070ceSShreyas NC 2914eee0e16fSJeeja KP strncpy(skl->skl_sst->lib_info[ref_count].name, 2915eee0e16fSJeeja KP str_elem->string, 2916eee0e16fSJeeja KP ARRAY_SIZE(skl->skl_sst->lib_info[ref_count].name)); 2917541070ceSShreyas NC ref_count++; 2918541070ceSShreyas NC break; 2919541070ceSShreyas NC 2920541070ceSShreyas NC default: 2921ecd286a9SColin Ian King dev_err(dev, "Not a string token %d\n", str_elem->token); 2922541070ceSShreyas NC break; 2923541070ceSShreyas NC } 2924db6ed55dSShreyas NC tkn_count++; 2925541070ceSShreyas NC 2926541070ceSShreyas NC return tkn_count; 2927541070ceSShreyas NC } 2928541070ceSShreyas NC 2929541070ceSShreyas NC static int skl_tplg_get_str_tkn(struct device *dev, 2930541070ceSShreyas NC struct snd_soc_tplg_vendor_array *array, 2931eee0e16fSJeeja KP struct skl *skl) 2932541070ceSShreyas NC { 2933541070ceSShreyas NC int tkn_count = 0, ret; 2934541070ceSShreyas NC struct snd_soc_tplg_vendor_string_elem *str_elem; 2935541070ceSShreyas NC 2936541070ceSShreyas NC str_elem = (struct snd_soc_tplg_vendor_string_elem *)array->value; 2937541070ceSShreyas NC while (tkn_count < array->num_elems) { 2938eee0e16fSJeeja KP ret = skl_tplg_fill_str_mfest_tkn(dev, str_elem, skl); 2939541070ceSShreyas NC str_elem++; 2940541070ceSShreyas NC 2941541070ceSShreyas NC if (ret < 0) 2942541070ceSShreyas NC return ret; 2943541070ceSShreyas NC 2944541070ceSShreyas NC tkn_count = tkn_count + ret; 2945541070ceSShreyas NC } 2946541070ceSShreyas NC 2947541070ceSShreyas NC return tkn_count; 2948541070ceSShreyas NC } 2949541070ceSShreyas NC 2950db6ed55dSShreyas NC static int skl_tplg_manifest_fill_fmt(struct device *dev, 2951db6ed55dSShreyas NC struct skl_module_iface *fmt, 2952db6ed55dSShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem, 2953db6ed55dSShreyas NC u32 dir, int fmt_idx) 2954db6ed55dSShreyas NC { 2955db6ed55dSShreyas NC struct skl_module_pin_fmt *dst_fmt; 2956db6ed55dSShreyas NC struct skl_module_fmt *mod_fmt; 2957db6ed55dSShreyas NC int ret; 2958db6ed55dSShreyas NC 2959db6ed55dSShreyas NC if (!fmt) 2960db6ed55dSShreyas NC return -EINVAL; 2961db6ed55dSShreyas NC 2962db6ed55dSShreyas NC switch (dir) { 2963db6ed55dSShreyas NC case SKL_DIR_IN: 2964db6ed55dSShreyas NC dst_fmt = &fmt->inputs[fmt_idx]; 2965db6ed55dSShreyas NC break; 2966db6ed55dSShreyas NC 2967db6ed55dSShreyas NC case SKL_DIR_OUT: 2968db6ed55dSShreyas NC dst_fmt = &fmt->outputs[fmt_idx]; 2969db6ed55dSShreyas NC break; 2970db6ed55dSShreyas NC 2971db6ed55dSShreyas NC default: 2972db6ed55dSShreyas NC dev_err(dev, "Invalid direction: %d\n", dir); 2973db6ed55dSShreyas NC return -EINVAL; 2974db6ed55dSShreyas NC } 2975db6ed55dSShreyas NC 2976db6ed55dSShreyas NC mod_fmt = &dst_fmt->fmt; 2977db6ed55dSShreyas NC 2978db6ed55dSShreyas NC switch (tkn_elem->token) { 2979db6ed55dSShreyas NC case SKL_TKN_MM_U32_INTF_PIN_ID: 2980db6ed55dSShreyas NC dst_fmt->id = tkn_elem->value; 2981db6ed55dSShreyas NC break; 2982db6ed55dSShreyas NC 2983db6ed55dSShreyas NC default: 2984db6ed55dSShreyas NC ret = skl_tplg_fill_fmt(dev, mod_fmt, tkn_elem->token, 2985db6ed55dSShreyas NC tkn_elem->value); 2986db6ed55dSShreyas NC if (ret < 0) 2987db6ed55dSShreyas NC return ret; 2988db6ed55dSShreyas NC break; 2989db6ed55dSShreyas NC } 2990db6ed55dSShreyas NC 2991db6ed55dSShreyas NC return 0; 2992db6ed55dSShreyas NC } 2993db6ed55dSShreyas NC 2994db6ed55dSShreyas NC static int skl_tplg_fill_mod_info(struct device *dev, 2995db6ed55dSShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem, 2996db6ed55dSShreyas NC struct skl_module *mod) 2997db6ed55dSShreyas NC { 2998db6ed55dSShreyas NC 2999db6ed55dSShreyas NC if (!mod) 3000db6ed55dSShreyas NC return -EINVAL; 3001db6ed55dSShreyas NC 3002db6ed55dSShreyas NC switch (tkn_elem->token) { 3003db6ed55dSShreyas NC case SKL_TKN_U8_IN_PIN_TYPE: 3004db6ed55dSShreyas NC mod->input_pin_type = tkn_elem->value; 3005db6ed55dSShreyas NC break; 3006db6ed55dSShreyas NC 3007db6ed55dSShreyas NC case SKL_TKN_U8_OUT_PIN_TYPE: 3008db6ed55dSShreyas NC mod->output_pin_type = tkn_elem->value; 3009db6ed55dSShreyas NC break; 3010db6ed55dSShreyas NC 3011db6ed55dSShreyas NC case SKL_TKN_U8_IN_QUEUE_COUNT: 3012db6ed55dSShreyas NC mod->max_input_pins = tkn_elem->value; 3013db6ed55dSShreyas NC break; 3014db6ed55dSShreyas NC 3015db6ed55dSShreyas NC case SKL_TKN_U8_OUT_QUEUE_COUNT: 3016db6ed55dSShreyas NC mod->max_output_pins = tkn_elem->value; 3017db6ed55dSShreyas NC break; 3018db6ed55dSShreyas NC 3019db6ed55dSShreyas NC case SKL_TKN_MM_U8_NUM_RES: 3020db6ed55dSShreyas NC mod->nr_resources = tkn_elem->value; 3021db6ed55dSShreyas NC break; 3022db6ed55dSShreyas NC 3023db6ed55dSShreyas NC case SKL_TKN_MM_U8_NUM_INTF: 3024db6ed55dSShreyas NC mod->nr_interfaces = tkn_elem->value; 3025db6ed55dSShreyas NC break; 3026db6ed55dSShreyas NC 3027db6ed55dSShreyas NC default: 3028db6ed55dSShreyas NC dev_err(dev, "Invalid mod info token %d", tkn_elem->token); 3029db6ed55dSShreyas NC return -EINVAL; 3030db6ed55dSShreyas NC } 3031db6ed55dSShreyas NC 3032db6ed55dSShreyas NC return 0; 3033db6ed55dSShreyas NC } 3034db6ed55dSShreyas NC 3035db6ed55dSShreyas NC 3036541070ceSShreyas NC static int skl_tplg_get_int_tkn(struct device *dev, 3037541070ceSShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem, 3038eee0e16fSJeeja KP struct skl *skl) 3039541070ceSShreyas NC { 3040db6ed55dSShreyas NC int tkn_count = 0, ret; 3041db6ed55dSShreyas NC static int mod_idx, res_val_idx, intf_val_idx, dir, pin_idx; 3042db6ed55dSShreyas NC struct skl_module_res *res = NULL; 3043db6ed55dSShreyas NC struct skl_module_iface *fmt = NULL; 3044db6ed55dSShreyas NC struct skl_module *mod = NULL; 3045db6ed55dSShreyas NC int i; 3046db6ed55dSShreyas NC 3047db6ed55dSShreyas NC if (skl->modules) { 3048db6ed55dSShreyas NC mod = skl->modules[mod_idx]; 3049db6ed55dSShreyas NC res = &mod->resources[res_val_idx]; 3050db6ed55dSShreyas NC fmt = &mod->formats[intf_val_idx]; 3051db6ed55dSShreyas NC } 3052541070ceSShreyas NC 3053541070ceSShreyas NC switch (tkn_elem->token) { 3054541070ceSShreyas NC case SKL_TKN_U32_LIB_COUNT: 3055eee0e16fSJeeja KP skl->skl_sst->lib_count = tkn_elem->value; 3056db6ed55dSShreyas NC break; 3057db6ed55dSShreyas NC 3058db6ed55dSShreyas NC case SKL_TKN_U8_NUM_MOD: 3059db6ed55dSShreyas NC skl->nr_modules = tkn_elem->value; 3060db6ed55dSShreyas NC skl->modules = devm_kcalloc(dev, skl->nr_modules, 3061db6ed55dSShreyas NC sizeof(*skl->modules), GFP_KERNEL); 3062db6ed55dSShreyas NC if (!skl->modules) 3063db6ed55dSShreyas NC return -ENOMEM; 3064db6ed55dSShreyas NC 3065db6ed55dSShreyas NC for (i = 0; i < skl->nr_modules; i++) { 3066db6ed55dSShreyas NC skl->modules[i] = devm_kzalloc(dev, 3067db6ed55dSShreyas NC sizeof(struct skl_module), GFP_KERNEL); 3068db6ed55dSShreyas NC if (!skl->modules[i]) 3069db6ed55dSShreyas NC return -ENOMEM; 3070db6ed55dSShreyas NC } 3071db6ed55dSShreyas NC break; 3072db6ed55dSShreyas NC 3073db6ed55dSShreyas NC case SKL_TKN_MM_U8_MOD_IDX: 3074db6ed55dSShreyas NC mod_idx = tkn_elem->value; 3075db6ed55dSShreyas NC break; 3076db6ed55dSShreyas NC 3077db6ed55dSShreyas NC case SKL_TKN_U8_IN_PIN_TYPE: 3078db6ed55dSShreyas NC case SKL_TKN_U8_OUT_PIN_TYPE: 3079db6ed55dSShreyas NC case SKL_TKN_U8_IN_QUEUE_COUNT: 3080db6ed55dSShreyas NC case SKL_TKN_U8_OUT_QUEUE_COUNT: 3081db6ed55dSShreyas NC case SKL_TKN_MM_U8_NUM_RES: 3082db6ed55dSShreyas NC case SKL_TKN_MM_U8_NUM_INTF: 3083db6ed55dSShreyas NC ret = skl_tplg_fill_mod_info(dev, tkn_elem, mod); 3084db6ed55dSShreyas NC if (ret < 0) 3085db6ed55dSShreyas NC return ret; 3086db6ed55dSShreyas NC break; 3087db6ed55dSShreyas NC 3088db6ed55dSShreyas NC case SKL_TKN_U32_DIR_PIN_COUNT: 3089db6ed55dSShreyas NC dir = tkn_elem->value & SKL_IN_DIR_BIT_MASK; 3090db6ed55dSShreyas NC pin_idx = (tkn_elem->value & SKL_PIN_COUNT_MASK) >> 4; 3091db6ed55dSShreyas NC break; 3092db6ed55dSShreyas NC 3093db6ed55dSShreyas NC case SKL_TKN_MM_U32_RES_ID: 3094db6ed55dSShreyas NC if (!res) 3095db6ed55dSShreyas NC return -EINVAL; 3096db6ed55dSShreyas NC 3097db6ed55dSShreyas NC res->id = tkn_elem->value; 3098db6ed55dSShreyas NC res_val_idx = tkn_elem->value; 3099db6ed55dSShreyas NC break; 3100db6ed55dSShreyas NC 3101db6ed55dSShreyas NC case SKL_TKN_MM_U32_FMT_ID: 3102db6ed55dSShreyas NC if (!fmt) 3103db6ed55dSShreyas NC return -EINVAL; 3104db6ed55dSShreyas NC 3105db6ed55dSShreyas NC fmt->fmt_idx = tkn_elem->value; 3106db6ed55dSShreyas NC intf_val_idx = tkn_elem->value; 3107db6ed55dSShreyas NC break; 3108db6ed55dSShreyas NC 3109db6ed55dSShreyas NC case SKL_TKN_MM_U32_CPS: 3110db6ed55dSShreyas NC case SKL_TKN_MM_U32_DMA_SIZE: 3111db6ed55dSShreyas NC case SKL_TKN_MM_U32_CPC: 3112db6ed55dSShreyas NC case SKL_TKN_U32_MEM_PAGES: 3113db6ed55dSShreyas NC case SKL_TKN_U32_OBS: 3114db6ed55dSShreyas NC case SKL_TKN_U32_IBS: 3115db6ed55dSShreyas NC case SKL_TKN_MM_U32_RES_PIN_ID: 3116db6ed55dSShreyas NC case SKL_TKN_MM_U32_PIN_BUF: 3117db6ed55dSShreyas NC ret = skl_tplg_fill_res_tkn(dev, tkn_elem, res, pin_idx, dir); 3118db6ed55dSShreyas NC if (ret < 0) 3119db6ed55dSShreyas NC return ret; 3120db6ed55dSShreyas NC 3121db6ed55dSShreyas NC break; 3122db6ed55dSShreyas NC 3123db6ed55dSShreyas NC case SKL_TKN_MM_U32_NUM_IN_FMT: 3124db6ed55dSShreyas NC if (!fmt) 3125db6ed55dSShreyas NC return -EINVAL; 3126db6ed55dSShreyas NC 3127db6ed55dSShreyas NC res->nr_input_pins = tkn_elem->value; 3128db6ed55dSShreyas NC break; 3129db6ed55dSShreyas NC 3130db6ed55dSShreyas NC case SKL_TKN_MM_U32_NUM_OUT_FMT: 3131db6ed55dSShreyas NC if (!fmt) 3132db6ed55dSShreyas NC return -EINVAL; 3133db6ed55dSShreyas NC 3134db6ed55dSShreyas NC res->nr_output_pins = tkn_elem->value; 3135db6ed55dSShreyas NC break; 3136db6ed55dSShreyas NC 3137db6ed55dSShreyas NC case SKL_TKN_U32_FMT_CH: 3138db6ed55dSShreyas NC case SKL_TKN_U32_FMT_FREQ: 3139db6ed55dSShreyas NC case SKL_TKN_U32_FMT_BIT_DEPTH: 3140db6ed55dSShreyas NC case SKL_TKN_U32_FMT_SAMPLE_SIZE: 3141db6ed55dSShreyas NC case SKL_TKN_U32_FMT_CH_CONFIG: 3142db6ed55dSShreyas NC case SKL_TKN_U32_FMT_INTERLEAVE: 3143db6ed55dSShreyas NC case SKL_TKN_U32_FMT_SAMPLE_TYPE: 3144db6ed55dSShreyas NC case SKL_TKN_U32_FMT_CH_MAP: 3145db6ed55dSShreyas NC case SKL_TKN_MM_U32_INTF_PIN_ID: 3146db6ed55dSShreyas NC ret = skl_tplg_manifest_fill_fmt(dev, fmt, tkn_elem, 3147db6ed55dSShreyas NC dir, pin_idx); 3148db6ed55dSShreyas NC if (ret < 0) 3149db6ed55dSShreyas NC return ret; 3150541070ceSShreyas NC break; 3151541070ceSShreyas NC 3152541070ceSShreyas NC default: 3153ecd286a9SColin Ian King dev_err(dev, "Not a manifest token %d\n", tkn_elem->token); 3154541070ceSShreyas NC return -EINVAL; 3155541070ceSShreyas NC } 3156db6ed55dSShreyas NC tkn_count++; 3157541070ceSShreyas NC 3158541070ceSShreyas NC return tkn_count; 3159541070ceSShreyas NC } 3160541070ceSShreyas NC 3161db6ed55dSShreyas NC static int skl_tplg_get_manifest_uuid(struct device *dev, 3162db6ed55dSShreyas NC struct skl *skl, 3163db6ed55dSShreyas NC struct snd_soc_tplg_vendor_uuid_elem *uuid_tkn) 3164db6ed55dSShreyas NC { 3165db6ed55dSShreyas NC static int ref_count; 3166db6ed55dSShreyas NC struct skl_module *mod; 3167db6ed55dSShreyas NC 3168db6ed55dSShreyas NC if (uuid_tkn->token == SKL_TKN_UUID) { 3169db6ed55dSShreyas NC mod = skl->modules[ref_count]; 3170db6ed55dSShreyas NC memcpy(&mod->uuid, &uuid_tkn->uuid, sizeof(uuid_tkn->uuid)); 3171db6ed55dSShreyas NC ref_count++; 3172db6ed55dSShreyas NC } else { 3173db6ed55dSShreyas NC dev_err(dev, "Not an UUID token tkn %d\n", uuid_tkn->token); 3174db6ed55dSShreyas NC return -EINVAL; 3175db6ed55dSShreyas NC } 3176db6ed55dSShreyas NC 3177db6ed55dSShreyas NC return 0; 3178db6ed55dSShreyas NC } 3179db6ed55dSShreyas NC 3180541070ceSShreyas NC /* 3181541070ceSShreyas NC * Fill the manifest structure by parsing the tokens based on the 3182541070ceSShreyas NC * type. 3183541070ceSShreyas NC */ 3184541070ceSShreyas NC static int skl_tplg_get_manifest_tkn(struct device *dev, 3185eee0e16fSJeeja KP char *pvt_data, struct skl *skl, 3186541070ceSShreyas NC int block_size) 3187541070ceSShreyas NC { 3188541070ceSShreyas NC int tkn_count = 0, ret; 3189541070ceSShreyas NC int off = 0, tuple_size = 0; 3190541070ceSShreyas NC struct snd_soc_tplg_vendor_array *array; 3191541070ceSShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem; 3192541070ceSShreyas NC 3193541070ceSShreyas NC if (block_size <= 0) 3194541070ceSShreyas NC return -EINVAL; 3195541070ceSShreyas NC 3196541070ceSShreyas NC while (tuple_size < block_size) { 3197541070ceSShreyas NC array = (struct snd_soc_tplg_vendor_array *)(pvt_data + off); 3198541070ceSShreyas NC off += array->size; 3199541070ceSShreyas NC switch (array->type) { 3200541070ceSShreyas NC case SND_SOC_TPLG_TUPLE_TYPE_STRING: 3201eee0e16fSJeeja KP ret = skl_tplg_get_str_tkn(dev, array, skl); 3202541070ceSShreyas NC 3203541070ceSShreyas NC if (ret < 0) 3204541070ceSShreyas NC return ret; 32050a716776SShreyas NC tkn_count = ret; 3206541070ceSShreyas NC 3207541070ceSShreyas NC tuple_size += tkn_count * 3208541070ceSShreyas NC sizeof(struct snd_soc_tplg_vendor_string_elem); 3209541070ceSShreyas NC continue; 3210541070ceSShreyas NC 3211541070ceSShreyas NC case SND_SOC_TPLG_TUPLE_TYPE_UUID: 3212db6ed55dSShreyas NC ret = skl_tplg_get_manifest_uuid(dev, skl, array->uuid); 3213db6ed55dSShreyas NC if (ret < 0) 3214db6ed55dSShreyas NC return ret; 3215db6ed55dSShreyas NC 3216db6ed55dSShreyas NC tuple_size += sizeof(*array->uuid); 3217541070ceSShreyas NC continue; 3218541070ceSShreyas NC 3219541070ceSShreyas NC default: 3220541070ceSShreyas NC tkn_elem = array->value; 3221541070ceSShreyas NC tkn_count = 0; 3222541070ceSShreyas NC break; 3223541070ceSShreyas NC } 3224541070ceSShreyas NC 3225541070ceSShreyas NC while (tkn_count <= array->num_elems - 1) { 3226541070ceSShreyas NC ret = skl_tplg_get_int_tkn(dev, 3227eee0e16fSJeeja KP tkn_elem, skl); 3228541070ceSShreyas NC if (ret < 0) 3229541070ceSShreyas NC return ret; 3230541070ceSShreyas NC 3231541070ceSShreyas NC tkn_count = tkn_count + ret; 3232541070ceSShreyas NC tkn_elem++; 3233541070ceSShreyas NC } 32349fc129f6SShreyas NC tuple_size += (tkn_count * sizeof(*tkn_elem)); 3235541070ceSShreyas NC tkn_count = 0; 3236541070ceSShreyas NC } 3237541070ceSShreyas NC 32389fc129f6SShreyas NC return off; 3239541070ceSShreyas NC } 3240541070ceSShreyas NC 3241541070ceSShreyas NC /* 3242541070ceSShreyas NC * Parse manifest private data for tokens. The private data block is 3243541070ceSShreyas NC * preceded by descriptors for type and size of data block. 3244541070ceSShreyas NC */ 3245541070ceSShreyas NC static int skl_tplg_get_manifest_data(struct snd_soc_tplg_manifest *manifest, 3246eee0e16fSJeeja KP struct device *dev, struct skl *skl) 3247541070ceSShreyas NC { 3248541070ceSShreyas NC struct snd_soc_tplg_vendor_array *array; 3249541070ceSShreyas NC int num_blocks, block_size = 0, block_type, off = 0; 3250541070ceSShreyas NC char *data; 3251541070ceSShreyas NC int ret; 3252541070ceSShreyas NC 3253541070ceSShreyas NC /* Read the NUM_DATA_BLOCKS descriptor */ 3254541070ceSShreyas NC array = (struct snd_soc_tplg_vendor_array *)manifest->priv.data; 3255541070ceSShreyas NC ret = skl_tplg_get_desc_blocks(dev, array); 3256541070ceSShreyas NC if (ret < 0) 3257541070ceSShreyas NC return ret; 3258541070ceSShreyas NC num_blocks = ret; 3259541070ceSShreyas NC 3260541070ceSShreyas NC off += array->size; 3261541070ceSShreyas NC /* Read the BLOCK_TYPE and BLOCK_SIZE descriptor */ 3262541070ceSShreyas NC while (num_blocks > 0) { 32639fc129f6SShreyas NC array = (struct snd_soc_tplg_vendor_array *) 32649fc129f6SShreyas NC (manifest->priv.data + off); 3265541070ceSShreyas NC ret = skl_tplg_get_desc_blocks(dev, array); 3266541070ceSShreyas NC 3267541070ceSShreyas NC if (ret < 0) 3268541070ceSShreyas NC return ret; 3269541070ceSShreyas NC block_type = ret; 3270541070ceSShreyas NC off += array->size; 3271541070ceSShreyas NC 3272541070ceSShreyas NC array = (struct snd_soc_tplg_vendor_array *) 3273541070ceSShreyas NC (manifest->priv.data + off); 3274541070ceSShreyas NC 3275541070ceSShreyas NC ret = skl_tplg_get_desc_blocks(dev, array); 3276541070ceSShreyas NC 3277541070ceSShreyas NC if (ret < 0) 3278541070ceSShreyas NC return ret; 3279541070ceSShreyas NC block_size = ret; 3280541070ceSShreyas NC off += array->size; 3281541070ceSShreyas NC 3282541070ceSShreyas NC array = (struct snd_soc_tplg_vendor_array *) 3283541070ceSShreyas NC (manifest->priv.data + off); 3284541070ceSShreyas NC 3285541070ceSShreyas NC data = (manifest->priv.data + off); 3286541070ceSShreyas NC 3287541070ceSShreyas NC if (block_type == SKL_TYPE_TUPLE) { 3288eee0e16fSJeeja KP ret = skl_tplg_get_manifest_tkn(dev, data, skl, 3289541070ceSShreyas NC block_size); 3290541070ceSShreyas NC 3291541070ceSShreyas NC if (ret < 0) 3292541070ceSShreyas NC return ret; 3293541070ceSShreyas NC 3294541070ceSShreyas NC --num_blocks; 3295541070ceSShreyas NC } else { 3296541070ceSShreyas NC return -EINVAL; 3297541070ceSShreyas NC } 32989fc129f6SShreyas NC off += ret; 3299541070ceSShreyas NC } 3300541070ceSShreyas NC 3301541070ceSShreyas NC return 0; 3302541070ceSShreyas NC } 3303541070ceSShreyas NC 330415ecaba9SKranthi G static int skl_manifest_load(struct snd_soc_component *cmpnt, 330515ecaba9SKranthi G struct snd_soc_tplg_manifest *manifest) 330615ecaba9SKranthi G { 330715ecaba9SKranthi G struct hdac_ext_bus *ebus = snd_soc_component_get_drvdata(cmpnt); 330815ecaba9SKranthi G struct hdac_bus *bus = ebus_to_hbus(ebus); 330915ecaba9SKranthi G struct skl *skl = ebus_to_skl(ebus); 331015ecaba9SKranthi G 3311c15ad605SVinod Koul /* proceed only if we have private data defined */ 3312c15ad605SVinod Koul if (manifest->priv.size == 0) 3313c15ad605SVinod Koul return 0; 3314c15ad605SVinod Koul 3315eee0e16fSJeeja KP skl_tplg_get_manifest_data(manifest, bus->dev, skl); 3316541070ceSShreyas NC 3317eee0e16fSJeeja KP if (skl->skl_sst->lib_count > SKL_MAX_LIB) { 331815ecaba9SKranthi G dev_err(bus->dev, "Exceeding max Library count. Got:%d\n", 3319eee0e16fSJeeja KP skl->skl_sst->lib_count); 3320eee0e16fSJeeja KP return -EINVAL; 332115ecaba9SKranthi G } 332215ecaba9SKranthi G 3323eee0e16fSJeeja KP return 0; 332415ecaba9SKranthi G } 332515ecaba9SKranthi G 33263af36706SVinod Koul static struct snd_soc_tplg_ops skl_tplg_ops = { 33273af36706SVinod Koul .widget_load = skl_tplg_widget_load, 3328140adfbaSJeeja KP .control_load = skl_tplg_control_load, 3329140adfbaSJeeja KP .bytes_ext_ops = skl_tlv_ops, 3330140adfbaSJeeja KP .bytes_ext_ops_count = ARRAY_SIZE(skl_tlv_ops), 33317a1b749bSDharageswari R .io_ops = skl_tplg_kcontrol_ops, 33327a1b749bSDharageswari R .io_ops_count = ARRAY_SIZE(skl_tplg_kcontrol_ops), 333315ecaba9SKranthi G .manifest = skl_manifest_load, 3334606e21fdSGuneshwor Singh .dai_load = skl_dai_load, 33353af36706SVinod Koul }; 33363af36706SVinod Koul 3337287af4f9SJeeja KP /* 3338287af4f9SJeeja KP * A pipe can have multiple modules, each of them will be a DAPM widget as 3339287af4f9SJeeja KP * well. While managing a pipeline we need to get the list of all the 3340287af4f9SJeeja KP * widgets in a pipelines, so this helper - skl_tplg_create_pipe_widget_list() 3341287af4f9SJeeja KP * helps to get the SKL type widgets in that pipeline 3342287af4f9SJeeja KP */ 3343287af4f9SJeeja KP static int skl_tplg_create_pipe_widget_list(struct snd_soc_platform *platform) 3344287af4f9SJeeja KP { 3345287af4f9SJeeja KP struct snd_soc_dapm_widget *w; 3346287af4f9SJeeja KP struct skl_module_cfg *mcfg = NULL; 3347287af4f9SJeeja KP struct skl_pipe_module *p_module = NULL; 3348287af4f9SJeeja KP struct skl_pipe *pipe; 3349287af4f9SJeeja KP 3350287af4f9SJeeja KP list_for_each_entry(w, &platform->component.card->widgets, list) { 3351287af4f9SJeeja KP if (is_skl_dsp_widget_type(w) && w->priv != NULL) { 3352287af4f9SJeeja KP mcfg = w->priv; 3353287af4f9SJeeja KP pipe = mcfg->pipe; 3354287af4f9SJeeja KP 3355287af4f9SJeeja KP p_module = devm_kzalloc(platform->dev, 3356287af4f9SJeeja KP sizeof(*p_module), GFP_KERNEL); 3357287af4f9SJeeja KP if (!p_module) 3358287af4f9SJeeja KP return -ENOMEM; 3359287af4f9SJeeja KP 3360287af4f9SJeeja KP p_module->w = w; 3361287af4f9SJeeja KP list_add_tail(&p_module->node, &pipe->w_list); 3362287af4f9SJeeja KP } 3363287af4f9SJeeja KP } 3364287af4f9SJeeja KP 3365287af4f9SJeeja KP return 0; 3366287af4f9SJeeja KP } 3367287af4f9SJeeja KP 3368f0aa94faSJeeja KP static void skl_tplg_set_pipe_type(struct skl *skl, struct skl_pipe *pipe) 3369f0aa94faSJeeja KP { 3370f0aa94faSJeeja KP struct skl_pipe_module *w_module; 3371f0aa94faSJeeja KP struct snd_soc_dapm_widget *w; 3372f0aa94faSJeeja KP struct skl_module_cfg *mconfig; 3373f0aa94faSJeeja KP bool host_found = false, link_found = false; 3374f0aa94faSJeeja KP 3375f0aa94faSJeeja KP list_for_each_entry(w_module, &pipe->w_list, node) { 3376f0aa94faSJeeja KP w = w_module->w; 3377f0aa94faSJeeja KP mconfig = w->priv; 3378f0aa94faSJeeja KP 3379f0aa94faSJeeja KP if (mconfig->dev_type == SKL_DEVICE_HDAHOST) 3380f0aa94faSJeeja KP host_found = true; 3381f0aa94faSJeeja KP else if (mconfig->dev_type != SKL_DEVICE_NONE) 3382f0aa94faSJeeja KP link_found = true; 3383f0aa94faSJeeja KP } 3384f0aa94faSJeeja KP 3385f0aa94faSJeeja KP if (host_found && link_found) 3386f0aa94faSJeeja KP pipe->passthru = true; 3387f0aa94faSJeeja KP else 3388f0aa94faSJeeja KP pipe->passthru = false; 3389f0aa94faSJeeja KP } 3390f0aa94faSJeeja KP 33913af36706SVinod Koul /* This will be read from topology manifest, currently defined here */ 33923af36706SVinod Koul #define SKL_MAX_MCPS 30000000 33933af36706SVinod Koul #define SKL_FW_MAX_MEM 1000000 33943af36706SVinod Koul 33953af36706SVinod Koul /* 33963af36706SVinod Koul * SKL topology init routine 33973af36706SVinod Koul */ 33983af36706SVinod Koul int skl_tplg_init(struct snd_soc_platform *platform, struct hdac_ext_bus *ebus) 33993af36706SVinod Koul { 34003af36706SVinod Koul int ret; 34013af36706SVinod Koul const struct firmware *fw; 34023af36706SVinod Koul struct hdac_bus *bus = ebus_to_hbus(ebus); 34033af36706SVinod Koul struct skl *skl = ebus_to_skl(ebus); 3404f0aa94faSJeeja KP struct skl_pipeline *ppl; 34053af36706SVinod Koul 34064b235c43SVinod Koul ret = request_firmware(&fw, skl->tplg_name, bus->dev); 34073af36706SVinod Koul if (ret < 0) { 340819de7179SChintan Patel dev_info(bus->dev, "tplg fw %s load failed with %d, falling back to dfw_sst.bin", 34094b235c43SVinod Koul skl->tplg_name, ret); 34104b235c43SVinod Koul ret = request_firmware(&fw, "dfw_sst.bin", bus->dev); 34114b235c43SVinod Koul if (ret < 0) { 34124b235c43SVinod Koul dev_err(bus->dev, "Fallback tplg fw %s load failed with %d\n", 34133af36706SVinod Koul "dfw_sst.bin", ret); 34143af36706SVinod Koul return ret; 34153af36706SVinod Koul } 34164b235c43SVinod Koul } 34173af36706SVinod Koul 34183af36706SVinod Koul /* 34193af36706SVinod Koul * The complete tplg for SKL is loaded as index 0, we don't use 34203af36706SVinod Koul * any other index 34213af36706SVinod Koul */ 3422b663a8c5SJeeja KP ret = snd_soc_tplg_component_load(&platform->component, 3423b663a8c5SJeeja KP &skl_tplg_ops, fw, 0); 34243af36706SVinod Koul if (ret < 0) { 34253af36706SVinod Koul dev_err(bus->dev, "tplg component load failed%d\n", ret); 3426c14a82c7SSudip Mukherjee release_firmware(fw); 34273af36706SVinod Koul return -EINVAL; 34283af36706SVinod Koul } 34293af36706SVinod Koul 34303af36706SVinod Koul skl->resource.max_mcps = SKL_MAX_MCPS; 34313af36706SVinod Koul skl->resource.max_mem = SKL_FW_MAX_MEM; 34323af36706SVinod Koul 3433d8018361SVinod Koul skl->tplg = fw; 3434287af4f9SJeeja KP ret = skl_tplg_create_pipe_widget_list(platform); 3435287af4f9SJeeja KP if (ret < 0) 3436287af4f9SJeeja KP return ret; 3437d8018361SVinod Koul 3438f0aa94faSJeeja KP list_for_each_entry(ppl, &skl->ppl_list, node) 3439f0aa94faSJeeja KP skl_tplg_set_pipe_type(skl, ppl->pipe); 34403af36706SVinod Koul 34413af36706SVinod Koul return 0; 3442e4e2d2f4SJeeja KP } 3443