147d7195dSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2e4e2d2f4SJeeja KP /* 3e4e2d2f4SJeeja KP * skl-topology.c - Implements Platform component ALSA controls/widget 4e4e2d2f4SJeeja KP * handlers. 5e4e2d2f4SJeeja KP * 6e4e2d2f4SJeeja KP * Copyright (C) 2014-2015 Intel Corp 7e4e2d2f4SJeeja KP * Author: Jeeja KP <jeeja.kp@intel.com> 8e4e2d2f4SJeeja KP * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 9e4e2d2f4SJeeja KP */ 10e4e2d2f4SJeeja KP 11e4e2d2f4SJeeja KP #include <linux/slab.h> 12e4e2d2f4SJeeja KP #include <linux/types.h> 13e4e2d2f4SJeeja KP #include <linux/firmware.h> 14ac9391daSGuenter Roeck #include <linux/uuid.h> 15e4e2d2f4SJeeja KP #include <sound/soc.h> 16e4e2d2f4SJeeja KP #include <sound/soc-topology.h> 176277e832SShreyas NC #include <uapi/sound/snd_sst_tokens.h> 180c24fdc0SGuenter Roeck #include <uapi/sound/skl-tplg-interface.h> 19e4e2d2f4SJeeja KP #include "skl-sst-dsp.h" 20e4e2d2f4SJeeja KP #include "skl-sst-ipc.h" 21e4e2d2f4SJeeja KP #include "skl-topology.h" 22e4e2d2f4SJeeja KP #include "skl.h" 236c5768b3SDharageswari R #include "../common/sst-dsp.h" 246c5768b3SDharageswari R #include "../common/sst-dsp-priv.h" 25e4e2d2f4SJeeja KP 26f7590d4fSJeeja KP #define SKL_CH_FIXUP_MASK (1 << 0) 27f7590d4fSJeeja KP #define SKL_RATE_FIXUP_MASK (1 << 1) 28f7590d4fSJeeja KP #define SKL_FMT_FIXUP_MASK (1 << 2) 296277e832SShreyas NC #define SKL_IN_DIR_BIT_MASK BIT(0) 306277e832SShreyas NC #define SKL_PIN_COUNT_MASK GENMASK(7, 4) 31f7590d4fSJeeja KP 327a1b749bSDharageswari R static const int mic_mono_list[] = { 337a1b749bSDharageswari R 0, 1, 2, 3, 347a1b749bSDharageswari R }; 357a1b749bSDharageswari R static const int mic_stereo_list[][SKL_CH_STEREO] = { 367a1b749bSDharageswari R {0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}, 377a1b749bSDharageswari R }; 387a1b749bSDharageswari R static const int mic_trio_list[][SKL_CH_TRIO] = { 397a1b749bSDharageswari R {0, 1, 2}, {0, 1, 3}, {0, 2, 3}, {1, 2, 3}, 407a1b749bSDharageswari R }; 417a1b749bSDharageswari R static const int mic_quatro_list[][SKL_CH_QUATRO] = { 427a1b749bSDharageswari R {0, 1, 2, 3}, 437a1b749bSDharageswari R }; 447a1b749bSDharageswari R 45f6fa56e2SRamesh Babu #define CHECK_HW_PARAMS(ch, freq, bps, prm_ch, prm_freq, prm_bps) \ 46f6fa56e2SRamesh Babu ((ch == prm_ch) && (bps == prm_bps) && (freq == prm_freq)) 47f6fa56e2SRamesh Babu 48*bcc2a2dcSCezary Rojewski void skl_tplg_d0i3_get(struct skl_dev *skl, enum d0i3_capability caps) 49a83e3b4cSVinod Koul { 50*bcc2a2dcSCezary Rojewski struct skl_d0i3_data *d0i3 = &skl->d0i3; 51a83e3b4cSVinod Koul 52a83e3b4cSVinod Koul switch (caps) { 53a83e3b4cSVinod Koul case SKL_D0I3_NONE: 54a83e3b4cSVinod Koul d0i3->non_d0i3++; 55a83e3b4cSVinod Koul break; 56a83e3b4cSVinod Koul 57a83e3b4cSVinod Koul case SKL_D0I3_STREAMING: 58a83e3b4cSVinod Koul d0i3->streaming++; 59a83e3b4cSVinod Koul break; 60a83e3b4cSVinod Koul 61a83e3b4cSVinod Koul case SKL_D0I3_NON_STREAMING: 62a83e3b4cSVinod Koul d0i3->non_streaming++; 63a83e3b4cSVinod Koul break; 64a83e3b4cSVinod Koul } 65a83e3b4cSVinod Koul } 66a83e3b4cSVinod Koul 67*bcc2a2dcSCezary Rojewski void skl_tplg_d0i3_put(struct skl_dev *skl, enum d0i3_capability caps) 68a83e3b4cSVinod Koul { 69*bcc2a2dcSCezary Rojewski struct skl_d0i3_data *d0i3 = &skl->d0i3; 70a83e3b4cSVinod Koul 71a83e3b4cSVinod Koul switch (caps) { 72a83e3b4cSVinod Koul case SKL_D0I3_NONE: 73a83e3b4cSVinod Koul d0i3->non_d0i3--; 74a83e3b4cSVinod Koul break; 75a83e3b4cSVinod Koul 76a83e3b4cSVinod Koul case SKL_D0I3_STREAMING: 77a83e3b4cSVinod Koul d0i3->streaming--; 78a83e3b4cSVinod Koul break; 79a83e3b4cSVinod Koul 80a83e3b4cSVinod Koul case SKL_D0I3_NON_STREAMING: 81a83e3b4cSVinod Koul d0i3->non_streaming--; 82a83e3b4cSVinod Koul break; 83a83e3b4cSVinod Koul } 84a83e3b4cSVinod Koul } 85a83e3b4cSVinod Koul 86e4e2d2f4SJeeja KP /* 87e4e2d2f4SJeeja KP * SKL DSP driver modelling uses only few DAPM widgets so for rest we will 88e4e2d2f4SJeeja KP * ignore. This helpers checks if the SKL driver handles this widget type 89e4e2d2f4SJeeja KP */ 90cb1f904dSGuneshwor Singh static int is_skl_dsp_widget_type(struct snd_soc_dapm_widget *w, 91cb1f904dSGuneshwor Singh struct device *dev) 92e4e2d2f4SJeeja KP { 93cb1f904dSGuneshwor Singh if (w->dapm->dev != dev) 94cb1f904dSGuneshwor Singh return false; 95cb1f904dSGuneshwor Singh 96e4e2d2f4SJeeja KP switch (w->id) { 97e4e2d2f4SJeeja KP case snd_soc_dapm_dai_link: 98e4e2d2f4SJeeja KP case snd_soc_dapm_dai_in: 99e4e2d2f4SJeeja KP case snd_soc_dapm_aif_in: 100e4e2d2f4SJeeja KP case snd_soc_dapm_aif_out: 101e4e2d2f4SJeeja KP case snd_soc_dapm_dai_out: 102e4e2d2f4SJeeja KP case snd_soc_dapm_switch: 103fe65324eSRakesh Ughreja case snd_soc_dapm_output: 104fe65324eSRakesh Ughreja case snd_soc_dapm_mux: 105fe65324eSRakesh Ughreja 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 */ 116*bcc2a2dcSCezary Rojewski static bool skl_is_pipe_mem_avail(struct skl_dev *skl, 117e4e2d2f4SJeeja KP struct skl_module_cfg *mconfig) 118e4e2d2f4SJeeja KP { 119e4e2d2f4SJeeja KP if (skl->resource.mem + mconfig->pipe->memory_pages > 120e4e2d2f4SJeeja KP skl->resource.max_mem) { 121*bcc2a2dcSCezary Rojewski dev_err(skl->dev, 122e4e2d2f4SJeeja KP "%s: module_id %d instance %d\n", __func__, 123e4e2d2f4SJeeja KP mconfig->id.module_id, 124e4e2d2f4SJeeja KP mconfig->id.instance_id); 125*bcc2a2dcSCezary Rojewski dev_err(skl->dev, 126e4e2d2f4SJeeja KP "exceeds ppl memory available %d mem %d\n", 127e4e2d2f4SJeeja KP skl->resource.max_mem, skl->resource.mem); 128e4e2d2f4SJeeja KP return false; 1299ba8ffefSDharageswari.R } else { 1309ba8ffefSDharageswari.R return true; 1319ba8ffefSDharageswari.R } 132e4e2d2f4SJeeja KP } 133e4e2d2f4SJeeja KP 1349ba8ffefSDharageswari.R /* 1359ba8ffefSDharageswari.R * Add the mem to the mem pool. This is freed when pipe is deleted. 1369ba8ffefSDharageswari.R * Note: DSP does actual memory management we only keep track for complete 1379ba8ffefSDharageswari.R * pool 1389ba8ffefSDharageswari.R */ 139*bcc2a2dcSCezary Rojewski static void skl_tplg_alloc_pipe_mem(struct skl_dev *skl, 1409ba8ffefSDharageswari.R struct skl_module_cfg *mconfig) 1419ba8ffefSDharageswari.R { 142e4e2d2f4SJeeja KP skl->resource.mem += mconfig->pipe->memory_pages; 143e4e2d2f4SJeeja KP } 144e4e2d2f4SJeeja KP 145e4e2d2f4SJeeja KP /* 146e4e2d2f4SJeeja KP * Pipeline needs needs DSP CPU resources for computation, this is 147e4e2d2f4SJeeja KP * quantified in MCPS (Million Clocks Per Second) required for module/pipe 148e4e2d2f4SJeeja KP * 149e4e2d2f4SJeeja KP * Each pipelines needs mcps to be allocated. Check if we have mcps for this 1509ba8ffefSDharageswari.R * pipe. 151e4e2d2f4SJeeja KP */ 1529ba8ffefSDharageswari.R 153*bcc2a2dcSCezary Rojewski static bool skl_is_pipe_mcps_avail(struct skl_dev *skl, 154e4e2d2f4SJeeja KP struct skl_module_cfg *mconfig) 155e4e2d2f4SJeeja KP { 156f6fa56e2SRamesh Babu u8 res_idx = mconfig->res_idx; 157f6fa56e2SRamesh Babu struct skl_module_res *res = &mconfig->module->resources[res_idx]; 158e4e2d2f4SJeeja KP 159f6fa56e2SRamesh Babu if (skl->resource.mcps + res->cps > skl->resource.max_mcps) { 160*bcc2a2dcSCezary Rojewski dev_err(skl->dev, 161e4e2d2f4SJeeja KP "%s: module_id %d instance %d\n", __func__, 162e4e2d2f4SJeeja KP mconfig->id.module_id, mconfig->id.instance_id); 163*bcc2a2dcSCezary Rojewski dev_err(skl->dev, 1647ca42f5aSGuneshwor Singh "exceeds ppl mcps available %d > mem %d\n", 165e4e2d2f4SJeeja KP skl->resource.max_mcps, skl->resource.mcps); 166e4e2d2f4SJeeja KP return false; 1679ba8ffefSDharageswari.R } else { 1689ba8ffefSDharageswari.R return true; 1699ba8ffefSDharageswari.R } 170e4e2d2f4SJeeja KP } 171e4e2d2f4SJeeja KP 172*bcc2a2dcSCezary Rojewski static void skl_tplg_alloc_pipe_mcps(struct skl_dev *skl, 1739ba8ffefSDharageswari.R struct skl_module_cfg *mconfig) 1749ba8ffefSDharageswari.R { 175f6fa56e2SRamesh Babu u8 res_idx = mconfig->res_idx; 176f6fa56e2SRamesh Babu struct skl_module_res *res = &mconfig->module->resources[res_idx]; 177f6fa56e2SRamesh Babu 178f6fa56e2SRamesh Babu skl->resource.mcps += res->cps; 179e4e2d2f4SJeeja KP } 180e4e2d2f4SJeeja KP 181e4e2d2f4SJeeja KP /* 182e4e2d2f4SJeeja KP * Free the mcps when tearing down 183e4e2d2f4SJeeja KP */ 184e4e2d2f4SJeeja KP static void 185*bcc2a2dcSCezary Rojewski skl_tplg_free_pipe_mcps(struct skl_dev *skl, struct skl_module_cfg *mconfig) 186e4e2d2f4SJeeja KP { 187f6fa56e2SRamesh Babu u8 res_idx = mconfig->res_idx; 188f6fa56e2SRamesh Babu struct skl_module_res *res = &mconfig->module->resources[res_idx]; 189f6fa56e2SRamesh Babu 190f6fa56e2SRamesh Babu skl->resource.mcps -= res->cps; 191e4e2d2f4SJeeja KP } 192e4e2d2f4SJeeja KP 193e4e2d2f4SJeeja KP /* 194e4e2d2f4SJeeja KP * Free the memory when tearing down 195e4e2d2f4SJeeja KP */ 196e4e2d2f4SJeeja KP static void 197*bcc2a2dcSCezary Rojewski skl_tplg_free_pipe_mem(struct skl_dev *skl, struct skl_module_cfg *mconfig) 198e4e2d2f4SJeeja KP { 199e4e2d2f4SJeeja KP skl->resource.mem -= mconfig->pipe->memory_pages; 200e4e2d2f4SJeeja KP } 201e4e2d2f4SJeeja KP 202f7590d4fSJeeja KP 203*bcc2a2dcSCezary Rojewski static void skl_dump_mconfig(struct skl_dev *skl, struct skl_module_cfg *mcfg) 204f7590d4fSJeeja KP { 205f6fa56e2SRamesh Babu struct skl_module_iface *iface = &mcfg->module->formats[0]; 206f6fa56e2SRamesh Babu 207*bcc2a2dcSCezary Rojewski dev_dbg(skl->dev, "Dumping config\n"); 208*bcc2a2dcSCezary Rojewski dev_dbg(skl->dev, "Input Format:\n"); 209*bcc2a2dcSCezary Rojewski dev_dbg(skl->dev, "channels = %d\n", iface->inputs[0].fmt.channels); 210*bcc2a2dcSCezary Rojewski dev_dbg(skl->dev, "s_freq = %d\n", iface->inputs[0].fmt.s_freq); 211*bcc2a2dcSCezary Rojewski dev_dbg(skl->dev, "ch_cfg = %d\n", iface->inputs[0].fmt.ch_cfg); 212*bcc2a2dcSCezary Rojewski dev_dbg(skl->dev, "valid bit depth = %d\n", 213f6fa56e2SRamesh Babu iface->inputs[0].fmt.valid_bit_depth); 214*bcc2a2dcSCezary Rojewski dev_dbg(skl->dev, "Output Format:\n"); 215*bcc2a2dcSCezary Rojewski dev_dbg(skl->dev, "channels = %d\n", iface->outputs[0].fmt.channels); 216*bcc2a2dcSCezary Rojewski dev_dbg(skl->dev, "s_freq = %d\n", iface->outputs[0].fmt.s_freq); 217*bcc2a2dcSCezary Rojewski dev_dbg(skl->dev, "valid bit depth = %d\n", 218f6fa56e2SRamesh Babu iface->outputs[0].fmt.valid_bit_depth); 219*bcc2a2dcSCezary Rojewski dev_dbg(skl->dev, "ch_cfg = %d\n", iface->outputs[0].fmt.ch_cfg); 220f7590d4fSJeeja KP } 221f7590d4fSJeeja KP 222ea5a137dSSubhransu S. Prusty static void skl_tplg_update_chmap(struct skl_module_fmt *fmt, int chs) 223ea5a137dSSubhransu S. Prusty { 224ea5a137dSSubhransu S. Prusty int slot_map = 0xFFFFFFFF; 225ea5a137dSSubhransu S. Prusty int start_slot = 0; 226ea5a137dSSubhransu S. Prusty int i; 227ea5a137dSSubhransu S. Prusty 228ea5a137dSSubhransu S. Prusty for (i = 0; i < chs; i++) { 229ea5a137dSSubhransu S. Prusty /* 230ea5a137dSSubhransu S. Prusty * For 2 channels with starting slot as 0, slot map will 231ea5a137dSSubhransu S. Prusty * look like 0xFFFFFF10. 232ea5a137dSSubhransu S. Prusty */ 233ea5a137dSSubhransu S. Prusty slot_map &= (~(0xF << (4 * i)) | (start_slot << (4 * i))); 234ea5a137dSSubhransu S. Prusty start_slot++; 235ea5a137dSSubhransu S. Prusty } 236ea5a137dSSubhransu S. Prusty fmt->ch_map = slot_map; 237ea5a137dSSubhransu S. Prusty } 238ea5a137dSSubhransu S. Prusty 239f7590d4fSJeeja KP static void skl_tplg_update_params(struct skl_module_fmt *fmt, 240f7590d4fSJeeja KP struct skl_pipe_params *params, int fixup) 241f7590d4fSJeeja KP { 242f7590d4fSJeeja KP if (fixup & SKL_RATE_FIXUP_MASK) 243f7590d4fSJeeja KP fmt->s_freq = params->s_freq; 244ea5a137dSSubhransu S. Prusty if (fixup & SKL_CH_FIXUP_MASK) { 245f7590d4fSJeeja KP fmt->channels = params->ch; 246ea5a137dSSubhransu S. Prusty skl_tplg_update_chmap(fmt, fmt->channels); 247ea5a137dSSubhransu S. Prusty } 24898256f83SJeeja KP if (fixup & SKL_FMT_FIXUP_MASK) { 24998256f83SJeeja KP fmt->valid_bit_depth = skl_get_bit_depth(params->s_fmt); 25098256f83SJeeja KP 25198256f83SJeeja KP /* 25298256f83SJeeja KP * 16 bit is 16 bit container whereas 24 bit is in 32 bit 25398256f83SJeeja KP * container so update bit depth accordingly 25498256f83SJeeja KP */ 25598256f83SJeeja KP switch (fmt->valid_bit_depth) { 25698256f83SJeeja KP case SKL_DEPTH_16BIT: 25798256f83SJeeja KP fmt->bit_depth = fmt->valid_bit_depth; 25898256f83SJeeja KP break; 25998256f83SJeeja KP 26098256f83SJeeja KP default: 26198256f83SJeeja KP fmt->bit_depth = SKL_DEPTH_32BIT; 26298256f83SJeeja KP break; 26398256f83SJeeja KP } 26498256f83SJeeja KP } 26598256f83SJeeja KP 266f7590d4fSJeeja KP } 267f7590d4fSJeeja KP 268f7590d4fSJeeja KP /* 269f7590d4fSJeeja KP * A pipeline may have modules which impact the pcm parameters, like SRC, 270f7590d4fSJeeja KP * channel converter, format converter. 271f7590d4fSJeeja KP * We need to calculate the output params by applying the 'fixup' 272f7590d4fSJeeja KP * Topology will tell driver which type of fixup is to be applied by 273f7590d4fSJeeja KP * supplying the fixup mask, so based on that we calculate the output 274f7590d4fSJeeja KP * 275f7590d4fSJeeja KP * Now In FE the pcm hw_params is source/target format. Same is applicable 276f7590d4fSJeeja KP * for BE with its hw_params invoked. 277f7590d4fSJeeja KP * here based on FE, BE pipeline and direction we calculate the input and 278f7590d4fSJeeja KP * outfix and then apply that for a module 279f7590d4fSJeeja KP */ 280f7590d4fSJeeja KP static void skl_tplg_update_params_fixup(struct skl_module_cfg *m_cfg, 281f7590d4fSJeeja KP struct skl_pipe_params *params, bool is_fe) 282f7590d4fSJeeja KP { 283f7590d4fSJeeja KP int in_fixup, out_fixup; 284f7590d4fSJeeja KP struct skl_module_fmt *in_fmt, *out_fmt; 285f7590d4fSJeeja KP 2864cd9899fSHardik T Shah /* Fixups will be applied to pin 0 only */ 287f6fa56e2SRamesh Babu in_fmt = &m_cfg->module->formats[0].inputs[0].fmt; 288f6fa56e2SRamesh Babu out_fmt = &m_cfg->module->formats[0].outputs[0].fmt; 289f7590d4fSJeeja KP 290f7590d4fSJeeja KP if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) { 291f7590d4fSJeeja KP if (is_fe) { 292f7590d4fSJeeja KP in_fixup = m_cfg->params_fixup; 293f7590d4fSJeeja KP out_fixup = (~m_cfg->converter) & 294f7590d4fSJeeja KP m_cfg->params_fixup; 295f7590d4fSJeeja KP } else { 296f7590d4fSJeeja KP out_fixup = m_cfg->params_fixup; 297f7590d4fSJeeja KP in_fixup = (~m_cfg->converter) & 298f7590d4fSJeeja KP m_cfg->params_fixup; 299f7590d4fSJeeja KP } 300f7590d4fSJeeja KP } else { 301f7590d4fSJeeja KP if (is_fe) { 302f7590d4fSJeeja KP out_fixup = m_cfg->params_fixup; 303f7590d4fSJeeja KP in_fixup = (~m_cfg->converter) & 304f7590d4fSJeeja KP m_cfg->params_fixup; 305f7590d4fSJeeja KP } else { 306f7590d4fSJeeja KP in_fixup = m_cfg->params_fixup; 307f7590d4fSJeeja KP out_fixup = (~m_cfg->converter) & 308f7590d4fSJeeja KP m_cfg->params_fixup; 309f7590d4fSJeeja KP } 310f7590d4fSJeeja KP } 311f7590d4fSJeeja KP 312f7590d4fSJeeja KP skl_tplg_update_params(in_fmt, params, in_fixup); 313f7590d4fSJeeja KP skl_tplg_update_params(out_fmt, params, out_fixup); 314f7590d4fSJeeja KP } 315f7590d4fSJeeja KP 316f7590d4fSJeeja KP /* 317f7590d4fSJeeja KP * A module needs input and output buffers, which are dependent upon pcm 318f7590d4fSJeeja KP * params, so once we have calculate params, we need buffer calculation as 319f7590d4fSJeeja KP * well. 320f7590d4fSJeeja KP */ 321*bcc2a2dcSCezary Rojewski static void skl_tplg_update_buffer_size(struct skl_dev *skl, 322f7590d4fSJeeja KP struct skl_module_cfg *mcfg) 323f7590d4fSJeeja KP { 324f7590d4fSJeeja KP int multiplier = 1; 3254cd9899fSHardik T Shah struct skl_module_fmt *in_fmt, *out_fmt; 326f6fa56e2SRamesh Babu struct skl_module_res *res; 3274cd9899fSHardik T Shah 3284cd9899fSHardik T Shah /* Since fixups is applied to pin 0 only, ibs, obs needs 3294cd9899fSHardik T Shah * change for pin 0 only 3304cd9899fSHardik T Shah */ 331f6fa56e2SRamesh Babu res = &mcfg->module->resources[0]; 332f6fa56e2SRamesh Babu in_fmt = &mcfg->module->formats[0].inputs[0].fmt; 333f6fa56e2SRamesh Babu out_fmt = &mcfg->module->formats[0].outputs[0].fmt; 334f7590d4fSJeeja KP 335f7590d4fSJeeja KP if (mcfg->m_type == SKL_MODULE_TYPE_SRCINT) 336f7590d4fSJeeja KP multiplier = 5; 337f0c8e1d9SSubhransu S. Prusty 338f6fa56e2SRamesh Babu res->ibs = DIV_ROUND_UP(in_fmt->s_freq, 1000) * 339998d6fb5STakashi Sakamoto in_fmt->channels * (in_fmt->bit_depth >> 3) * 340f7590d4fSJeeja KP multiplier; 341f7590d4fSJeeja KP 342f6fa56e2SRamesh Babu res->obs = DIV_ROUND_UP(out_fmt->s_freq, 1000) * 343998d6fb5STakashi Sakamoto out_fmt->channels * (out_fmt->bit_depth >> 3) * 344f7590d4fSJeeja KP multiplier; 345f7590d4fSJeeja KP } 346f7590d4fSJeeja KP 347db2f586bSSenthilnathan Veppur static u8 skl_tplg_be_dev_type(int dev_type) 348db2f586bSSenthilnathan Veppur { 349db2f586bSSenthilnathan Veppur int ret; 350db2f586bSSenthilnathan Veppur 351db2f586bSSenthilnathan Veppur switch (dev_type) { 352db2f586bSSenthilnathan Veppur case SKL_DEVICE_BT: 353db2f586bSSenthilnathan Veppur ret = NHLT_DEVICE_BT; 354db2f586bSSenthilnathan Veppur break; 355db2f586bSSenthilnathan Veppur 356db2f586bSSenthilnathan Veppur case SKL_DEVICE_DMIC: 357db2f586bSSenthilnathan Veppur ret = NHLT_DEVICE_DMIC; 358db2f586bSSenthilnathan Veppur break; 359db2f586bSSenthilnathan Veppur 360db2f586bSSenthilnathan Veppur case SKL_DEVICE_I2S: 361db2f586bSSenthilnathan Veppur ret = NHLT_DEVICE_I2S; 362db2f586bSSenthilnathan Veppur break; 363db2f586bSSenthilnathan Veppur 364db2f586bSSenthilnathan Veppur default: 365db2f586bSSenthilnathan Veppur ret = NHLT_DEVICE_INVALID; 366db2f586bSSenthilnathan Veppur break; 367db2f586bSSenthilnathan Veppur } 368db2f586bSSenthilnathan Veppur 369db2f586bSSenthilnathan Veppur return ret; 370db2f586bSSenthilnathan Veppur } 371db2f586bSSenthilnathan Veppur 3722d1419a3SJeeja KP static int skl_tplg_update_be_blob(struct snd_soc_dapm_widget *w, 373*bcc2a2dcSCezary Rojewski struct skl_dev *skl) 3742d1419a3SJeeja KP { 3752d1419a3SJeeja KP struct skl_module_cfg *m_cfg = w->priv; 3762d1419a3SJeeja KP int link_type, dir; 3772d1419a3SJeeja KP u32 ch, s_freq, s_fmt; 3782d1419a3SJeeja KP struct nhlt_specific_cfg *cfg; 379db2f586bSSenthilnathan Veppur u8 dev_type = skl_tplg_be_dev_type(m_cfg->dev_type); 380f6fa56e2SRamesh Babu int fmt_idx = m_cfg->fmt_idx; 381f6fa56e2SRamesh Babu struct skl_module_iface *m_iface = &m_cfg->module->formats[fmt_idx]; 3822d1419a3SJeeja KP 3832d1419a3SJeeja KP /* check if we already have blob */ 3842d1419a3SJeeja KP if (m_cfg->formats_config.caps_size > 0) 3852d1419a3SJeeja KP return 0; 3862d1419a3SJeeja KP 387*bcc2a2dcSCezary Rojewski dev_dbg(skl->dev, "Applying default cfg blob\n"); 3882d1419a3SJeeja KP switch (m_cfg->dev_type) { 3892d1419a3SJeeja KP case SKL_DEVICE_DMIC: 3902d1419a3SJeeja KP link_type = NHLT_LINK_DMIC; 391c7c6c736SJeeja KP dir = SNDRV_PCM_STREAM_CAPTURE; 392f6fa56e2SRamesh Babu s_freq = m_iface->inputs[0].fmt.s_freq; 393f6fa56e2SRamesh Babu s_fmt = m_iface->inputs[0].fmt.bit_depth; 394f6fa56e2SRamesh Babu ch = m_iface->inputs[0].fmt.channels; 3952d1419a3SJeeja KP break; 3962d1419a3SJeeja KP 3972d1419a3SJeeja KP case SKL_DEVICE_I2S: 3982d1419a3SJeeja KP link_type = NHLT_LINK_SSP; 3992d1419a3SJeeja KP if (m_cfg->hw_conn_type == SKL_CONN_SOURCE) { 400c7c6c736SJeeja KP dir = SNDRV_PCM_STREAM_PLAYBACK; 401f6fa56e2SRamesh Babu s_freq = m_iface->outputs[0].fmt.s_freq; 402f6fa56e2SRamesh Babu s_fmt = m_iface->outputs[0].fmt.bit_depth; 403f6fa56e2SRamesh Babu ch = m_iface->outputs[0].fmt.channels; 404c7c6c736SJeeja KP } else { 405c7c6c736SJeeja KP dir = SNDRV_PCM_STREAM_CAPTURE; 406f6fa56e2SRamesh Babu s_freq = m_iface->inputs[0].fmt.s_freq; 407f6fa56e2SRamesh Babu s_fmt = m_iface->inputs[0].fmt.bit_depth; 408f6fa56e2SRamesh Babu ch = m_iface->inputs[0].fmt.channels; 4092d1419a3SJeeja KP } 4102d1419a3SJeeja KP break; 4112d1419a3SJeeja KP 4122d1419a3SJeeja KP default: 4132d1419a3SJeeja KP return -EINVAL; 4142d1419a3SJeeja KP } 4152d1419a3SJeeja KP 4162d1419a3SJeeja KP /* update the blob based on virtual bus_id and default params */ 4172d1419a3SJeeja KP cfg = skl_get_ep_blob(skl, m_cfg->vbus_id, link_type, 418db2f586bSSenthilnathan Veppur s_fmt, ch, s_freq, dir, dev_type); 4192d1419a3SJeeja KP if (cfg) { 4202d1419a3SJeeja KP m_cfg->formats_config.caps_size = cfg->size; 4212d1419a3SJeeja KP m_cfg->formats_config.caps = (u32 *) &cfg->caps; 4222d1419a3SJeeja KP } else { 423*bcc2a2dcSCezary Rojewski dev_err(skl->dev, "Blob NULL for id %x type %d dirn %d\n", 4242d1419a3SJeeja KP m_cfg->vbus_id, link_type, dir); 425*bcc2a2dcSCezary Rojewski dev_err(skl->dev, "PCM: ch %d, freq %d, fmt %d\n", 4262d1419a3SJeeja KP ch, s_freq, s_fmt); 4272d1419a3SJeeja KP return -EIO; 4282d1419a3SJeeja KP } 4292d1419a3SJeeja KP 4302d1419a3SJeeja KP return 0; 4312d1419a3SJeeja KP } 4322d1419a3SJeeja KP 433f7590d4fSJeeja KP static void skl_tplg_update_module_params(struct snd_soc_dapm_widget *w, 434*bcc2a2dcSCezary Rojewski struct skl_dev *skl) 435f7590d4fSJeeja KP { 436f7590d4fSJeeja KP struct skl_module_cfg *m_cfg = w->priv; 437f7590d4fSJeeja KP struct skl_pipe_params *params = m_cfg->pipe->p_params; 438f7590d4fSJeeja KP int p_conn_type = m_cfg->pipe->conn_type; 439f7590d4fSJeeja KP bool is_fe; 440f7590d4fSJeeja KP 441f7590d4fSJeeja KP if (!m_cfg->params_fixup) 442f7590d4fSJeeja KP return; 443f7590d4fSJeeja KP 444*bcc2a2dcSCezary Rojewski dev_dbg(skl->dev, "Mconfig for widget=%s BEFORE updation\n", 445f7590d4fSJeeja KP w->name); 446f7590d4fSJeeja KP 447*bcc2a2dcSCezary Rojewski skl_dump_mconfig(skl, m_cfg); 448f7590d4fSJeeja KP 449f7590d4fSJeeja KP if (p_conn_type == SKL_PIPE_CONN_TYPE_FE) 450f7590d4fSJeeja KP is_fe = true; 451f7590d4fSJeeja KP else 452f7590d4fSJeeja KP is_fe = false; 453f7590d4fSJeeja KP 454f7590d4fSJeeja KP skl_tplg_update_params_fixup(m_cfg, params, is_fe); 455*bcc2a2dcSCezary Rojewski skl_tplg_update_buffer_size(skl, m_cfg); 456f7590d4fSJeeja KP 457*bcc2a2dcSCezary Rojewski dev_dbg(skl->dev, "Mconfig for widget=%s AFTER updation\n", 458f7590d4fSJeeja KP w->name); 459f7590d4fSJeeja KP 460*bcc2a2dcSCezary Rojewski skl_dump_mconfig(skl, m_cfg); 461f7590d4fSJeeja KP } 462f7590d4fSJeeja KP 463e4e2d2f4SJeeja KP /* 464abb74003SJeeja KP * some modules can have multiple params set from user control and 465abb74003SJeeja KP * need to be set after module is initialized. If set_param flag is 466abb74003SJeeja KP * set module params will be done after module is initialised. 467abb74003SJeeja KP */ 468abb74003SJeeja KP static int skl_tplg_set_module_params(struct snd_soc_dapm_widget *w, 469*bcc2a2dcSCezary Rojewski struct skl_dev *skl) 470abb74003SJeeja KP { 471abb74003SJeeja KP int i, ret; 472abb74003SJeeja KP struct skl_module_cfg *mconfig = w->priv; 473abb74003SJeeja KP const struct snd_kcontrol_new *k; 474abb74003SJeeja KP struct soc_bytes_ext *sb; 475abb74003SJeeja KP struct skl_algo_data *bc; 476abb74003SJeeja KP struct skl_specific_cfg *sp_cfg; 477abb74003SJeeja KP 478abb74003SJeeja KP if (mconfig->formats_config.caps_size > 0 && 4794ced1827SJeeja KP mconfig->formats_config.set_params == SKL_PARAM_SET) { 480abb74003SJeeja KP sp_cfg = &mconfig->formats_config; 481*bcc2a2dcSCezary Rojewski ret = skl_set_module_params(skl, sp_cfg->caps, 482abb74003SJeeja KP sp_cfg->caps_size, 483abb74003SJeeja KP sp_cfg->param_id, mconfig); 484abb74003SJeeja KP if (ret < 0) 485abb74003SJeeja KP return ret; 486abb74003SJeeja KP } 487abb74003SJeeja KP 488abb74003SJeeja KP for (i = 0; i < w->num_kcontrols; i++) { 489abb74003SJeeja KP k = &w->kcontrol_news[i]; 490abb74003SJeeja KP if (k->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { 491abb74003SJeeja KP sb = (void *) k->private_value; 492abb74003SJeeja KP bc = (struct skl_algo_data *)sb->dobj.private; 493abb74003SJeeja KP 4944ced1827SJeeja KP if (bc->set_params == SKL_PARAM_SET) { 495*bcc2a2dcSCezary Rojewski ret = skl_set_module_params(skl, 4960d682104SDharageswari R (u32 *)bc->params, bc->size, 497abb74003SJeeja KP bc->param_id, mconfig); 498abb74003SJeeja KP if (ret < 0) 499abb74003SJeeja KP return ret; 500abb74003SJeeja KP } 501abb74003SJeeja KP } 502abb74003SJeeja KP } 503abb74003SJeeja KP 504abb74003SJeeja KP return 0; 505abb74003SJeeja KP } 506abb74003SJeeja KP 507abb74003SJeeja KP /* 508abb74003SJeeja KP * some module param can set from user control and this is required as 509abb74003SJeeja KP * when module is initailzed. if module param is required in init it is 510abb74003SJeeja KP * identifed by set_param flag. if set_param flag is not set, then this 511abb74003SJeeja KP * parameter needs to set as part of module init. 512abb74003SJeeja KP */ 513abb74003SJeeja KP static int skl_tplg_set_module_init_data(struct snd_soc_dapm_widget *w) 514abb74003SJeeja KP { 515abb74003SJeeja KP const struct snd_kcontrol_new *k; 516abb74003SJeeja KP struct soc_bytes_ext *sb; 517abb74003SJeeja KP struct skl_algo_data *bc; 518abb74003SJeeja KP struct skl_module_cfg *mconfig = w->priv; 519abb74003SJeeja KP int i; 520abb74003SJeeja KP 521abb74003SJeeja KP for (i = 0; i < w->num_kcontrols; i++) { 522abb74003SJeeja KP k = &w->kcontrol_news[i]; 523abb74003SJeeja KP if (k->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { 524abb74003SJeeja KP sb = (struct soc_bytes_ext *)k->private_value; 525abb74003SJeeja KP bc = (struct skl_algo_data *)sb->dobj.private; 526abb74003SJeeja KP 5274ced1827SJeeja KP if (bc->set_params != SKL_PARAM_INIT) 528abb74003SJeeja KP continue; 529abb74003SJeeja KP 530d1a6fe41STakashi Sakamoto mconfig->formats_config.caps = (u32 *)bc->params; 5310d682104SDharageswari R mconfig->formats_config.caps_size = bc->size; 532abb74003SJeeja KP 533abb74003SJeeja KP break; 534abb74003SJeeja KP } 535abb74003SJeeja KP } 536abb74003SJeeja KP 537abb74003SJeeja KP return 0; 538abb74003SJeeja KP } 539abb74003SJeeja KP 540*bcc2a2dcSCezary Rojewski static int skl_tplg_module_prepare(struct skl_dev *skl, struct skl_pipe *pipe, 541bb704a73SJeeja KP struct snd_soc_dapm_widget *w, struct skl_module_cfg *mcfg) 542bb704a73SJeeja KP { 543bb704a73SJeeja KP switch (mcfg->dev_type) { 544bb704a73SJeeja KP case SKL_DEVICE_HDAHOST: 545*bcc2a2dcSCezary Rojewski return skl_pcm_host_dma_prepare(skl->dev, pipe->p_params); 546bb704a73SJeeja KP 547bb704a73SJeeja KP case SKL_DEVICE_HDALINK: 548*bcc2a2dcSCezary Rojewski return skl_pcm_link_dma_prepare(skl->dev, pipe->p_params); 549bb704a73SJeeja KP } 550bb704a73SJeeja KP 551bb704a73SJeeja KP return 0; 552bb704a73SJeeja KP } 553bb704a73SJeeja KP 554abb74003SJeeja KP /* 555e4e2d2f4SJeeja KP * Inside a pipe instance, we can have various modules. These modules need 556e4e2d2f4SJeeja KP * to instantiated in DSP by invoking INIT_MODULE IPC, which is achieved by 557e4e2d2f4SJeeja KP * skl_init_module() routine, so invoke that for all modules in a pipeline 558e4e2d2f4SJeeja KP */ 559e4e2d2f4SJeeja KP static int 560*bcc2a2dcSCezary Rojewski skl_tplg_init_pipe_modules(struct skl_dev *skl, struct skl_pipe *pipe) 561e4e2d2f4SJeeja KP { 562e4e2d2f4SJeeja KP struct skl_pipe_module *w_module; 563e4e2d2f4SJeeja KP struct snd_soc_dapm_widget *w; 564e4e2d2f4SJeeja KP struct skl_module_cfg *mconfig; 565f6fa56e2SRamesh Babu u8 cfg_idx; 566e4e2d2f4SJeeja KP int ret = 0; 567e4e2d2f4SJeeja KP 568e4e2d2f4SJeeja KP list_for_each_entry(w_module, &pipe->w_list, node) { 5699e0784d0SAndy Shevchenko guid_t *uuid_mod; 570e4e2d2f4SJeeja KP w = w_module->w; 571e4e2d2f4SJeeja KP mconfig = w->priv; 572e4e2d2f4SJeeja KP 573b7c50555SVinod Koul /* check if module ids are populated */ 574b7c50555SVinod Koul if (mconfig->id.module_id < 0) { 575*bcc2a2dcSCezary Rojewski dev_err(skl->dev, 576a657ae7eSVinod Koul "module %pUL id not populated\n", 5779e0784d0SAndy Shevchenko (guid_t *)mconfig->guid); 578a657ae7eSVinod Koul return -EIO; 579b7c50555SVinod Koul } 580b7c50555SVinod Koul 581f6fa56e2SRamesh Babu cfg_idx = mconfig->pipe->cur_config_idx; 582f6fa56e2SRamesh Babu mconfig->fmt_idx = mconfig->mod_cfg[cfg_idx].fmt_idx; 583f6fa56e2SRamesh Babu mconfig->res_idx = mconfig->mod_cfg[cfg_idx].res_idx; 584f6fa56e2SRamesh Babu 585e4e2d2f4SJeeja KP /* check resource available */ 5869ba8ffefSDharageswari.R if (!skl_is_pipe_mcps_avail(skl, mconfig)) 587e4e2d2f4SJeeja KP return -ENOMEM; 588e4e2d2f4SJeeja KP 589*bcc2a2dcSCezary Rojewski if (mconfig->module->loadable && skl->dsp->fw_ops.load_mod) { 590*bcc2a2dcSCezary Rojewski ret = skl->dsp->fw_ops.load_mod(skl->dsp, 5916c5768b3SDharageswari R mconfig->id.module_id, mconfig->guid); 5926c5768b3SDharageswari R if (ret < 0) 5936c5768b3SDharageswari R return ret; 594d643678bSJeeja KP 595d643678bSJeeja KP mconfig->m_state = SKL_MODULE_LOADED; 5966c5768b3SDharageswari R } 5976c5768b3SDharageswari R 598bb704a73SJeeja KP /* prepare the DMA if the module is gateway cpr */ 599*bcc2a2dcSCezary Rojewski ret = skl_tplg_module_prepare(skl, pipe, w, mconfig); 600bb704a73SJeeja KP if (ret < 0) 601bb704a73SJeeja KP return ret; 602bb704a73SJeeja KP 6032d1419a3SJeeja KP /* update blob if blob is null for be with default value */ 604*bcc2a2dcSCezary Rojewski skl_tplg_update_be_blob(w, skl); 6052d1419a3SJeeja KP 606f7590d4fSJeeja KP /* 607f7590d4fSJeeja KP * apply fix/conversion to module params based on 608f7590d4fSJeeja KP * FE/BE params 609f7590d4fSJeeja KP */ 610*bcc2a2dcSCezary Rojewski skl_tplg_update_module_params(w, skl); 6119e0784d0SAndy Shevchenko uuid_mod = (guid_t *)mconfig->guid; 612*bcc2a2dcSCezary Rojewski mconfig->id.pvt_id = skl_get_pvt_id(skl, uuid_mod, 613b26199eaSJeeja KP mconfig->id.instance_id); 614ef2a352cSDharageswari R if (mconfig->id.pvt_id < 0) 615ef2a352cSDharageswari R return ret; 616abb74003SJeeja KP skl_tplg_set_module_init_data(w); 6174147a6e5SPardha Saradhi K 618*bcc2a2dcSCezary Rojewski ret = skl_dsp_get_core(skl->dsp, mconfig->core_id); 6194147a6e5SPardha Saradhi K if (ret < 0) { 620*bcc2a2dcSCezary Rojewski dev_err(skl->dev, "Failed to wake up core %d ret=%d\n", 6214147a6e5SPardha Saradhi K mconfig->core_id, ret); 6224147a6e5SPardha Saradhi K return ret; 6234147a6e5SPardha Saradhi K } 6244147a6e5SPardha Saradhi K 625*bcc2a2dcSCezary Rojewski ret = skl_init_module(skl, mconfig); 626ef2a352cSDharageswari R if (ret < 0) { 627*bcc2a2dcSCezary Rojewski skl_put_pvt_id(skl, uuid_mod, &mconfig->id.pvt_id); 6284147a6e5SPardha Saradhi K goto err; 629ef2a352cSDharageswari R } 630260eb73aSDharageswari R skl_tplg_alloc_pipe_mcps(skl, mconfig); 631*bcc2a2dcSCezary Rojewski ret = skl_tplg_set_module_params(w, skl); 632e4e2d2f4SJeeja KP if (ret < 0) 6334147a6e5SPardha Saradhi K goto err; 634e4e2d2f4SJeeja KP } 635e4e2d2f4SJeeja KP 636e4e2d2f4SJeeja KP return 0; 6374147a6e5SPardha Saradhi K err: 638*bcc2a2dcSCezary Rojewski skl_dsp_put_core(skl->dsp, mconfig->core_id); 6394147a6e5SPardha Saradhi K return ret; 640e4e2d2f4SJeeja KP } 641d93f8e55SVinod Koul 642*bcc2a2dcSCezary Rojewski static int skl_tplg_unload_pipe_modules(struct skl_dev *skl, 6436c5768b3SDharageswari R struct skl_pipe *pipe) 6446c5768b3SDharageswari R { 6454147a6e5SPardha Saradhi K int ret = 0; 6466c5768b3SDharageswari R struct skl_pipe_module *w_module = NULL; 6476c5768b3SDharageswari R struct skl_module_cfg *mconfig = NULL; 6486c5768b3SDharageswari R 6496c5768b3SDharageswari R list_for_each_entry(w_module, &pipe->w_list, node) { 6509e0784d0SAndy Shevchenko guid_t *uuid_mod; 6516c5768b3SDharageswari R mconfig = w_module->w->priv; 6529e0784d0SAndy Shevchenko uuid_mod = (guid_t *)mconfig->guid; 6536c5768b3SDharageswari R 654*bcc2a2dcSCezary Rojewski if (mconfig->module->loadable && skl->dsp->fw_ops.unload_mod && 655b0fab9c6SDharageswari R mconfig->m_state > SKL_MODULE_UNINIT) { 656*bcc2a2dcSCezary Rojewski ret = skl->dsp->fw_ops.unload_mod(skl->dsp, 6576c5768b3SDharageswari R mconfig->id.module_id); 658b0fab9c6SDharageswari R if (ret < 0) 659b0fab9c6SDharageswari R return -EIO; 660b0fab9c6SDharageswari R } 661*bcc2a2dcSCezary Rojewski skl_put_pvt_id(skl, uuid_mod, &mconfig->id.pvt_id); 6624147a6e5SPardha Saradhi K 663*bcc2a2dcSCezary Rojewski ret = skl_dsp_put_core(skl->dsp, mconfig->core_id); 6644147a6e5SPardha Saradhi K if (ret < 0) { 6654147a6e5SPardha Saradhi K /* don't return; continue with other modules */ 666*bcc2a2dcSCezary Rojewski dev_err(skl->dev, "Failed to sleep core %d ret=%d\n", 6674147a6e5SPardha Saradhi K mconfig->core_id, ret); 6684147a6e5SPardha Saradhi K } 6696c5768b3SDharageswari R } 6706c5768b3SDharageswari R 6716c5768b3SDharageswari R /* no modules to unload in this path, so return */ 6724147a6e5SPardha Saradhi K return ret; 6736c5768b3SDharageswari R } 6746c5768b3SDharageswari R 675d93f8e55SVinod Koul /* 676f6fa56e2SRamesh Babu * Here, we select pipe format based on the pipe type and pipe 677f6fa56e2SRamesh Babu * direction to determine the current config index for the pipeline. 678f6fa56e2SRamesh Babu * The config index is then used to select proper module resources. 679f6fa56e2SRamesh Babu * Intermediate pipes currently have a fixed format hence we select the 680f6fa56e2SRamesh Babu * 0th configuratation by default for such pipes. 681f6fa56e2SRamesh Babu */ 682f6fa56e2SRamesh Babu static int 683*bcc2a2dcSCezary Rojewski skl_tplg_get_pipe_config(struct skl_dev *skl, struct skl_module_cfg *mconfig) 684f6fa56e2SRamesh Babu { 685f6fa56e2SRamesh Babu struct skl_pipe *pipe = mconfig->pipe; 686f6fa56e2SRamesh Babu struct skl_pipe_params *params = pipe->p_params; 687f6fa56e2SRamesh Babu struct skl_path_config *pconfig = &pipe->configs[0]; 688f6fa56e2SRamesh Babu struct skl_pipe_fmt *fmt = NULL; 689f6fa56e2SRamesh Babu bool in_fmt = false; 690f6fa56e2SRamesh Babu int i; 691f6fa56e2SRamesh Babu 692f6fa56e2SRamesh Babu if (pipe->nr_cfgs == 0) { 693f6fa56e2SRamesh Babu pipe->cur_config_idx = 0; 694f6fa56e2SRamesh Babu return 0; 695f6fa56e2SRamesh Babu } 696f6fa56e2SRamesh Babu 697f6fa56e2SRamesh Babu if (pipe->conn_type == SKL_PIPE_CONN_TYPE_NONE) { 698*bcc2a2dcSCezary Rojewski dev_dbg(skl->dev, "No conn_type detected, take 0th config\n"); 699f6fa56e2SRamesh Babu pipe->cur_config_idx = 0; 700f6fa56e2SRamesh Babu pipe->memory_pages = pconfig->mem_pages; 701f6fa56e2SRamesh Babu 702f6fa56e2SRamesh Babu return 0; 703f6fa56e2SRamesh Babu } 704f6fa56e2SRamesh Babu 705f6fa56e2SRamesh Babu if ((pipe->conn_type == SKL_PIPE_CONN_TYPE_FE && 706f6fa56e2SRamesh Babu pipe->direction == SNDRV_PCM_STREAM_PLAYBACK) || 707f6fa56e2SRamesh Babu (pipe->conn_type == SKL_PIPE_CONN_TYPE_BE && 708f6fa56e2SRamesh Babu pipe->direction == SNDRV_PCM_STREAM_CAPTURE)) 709f6fa56e2SRamesh Babu in_fmt = true; 710f6fa56e2SRamesh Babu 711f6fa56e2SRamesh Babu for (i = 0; i < pipe->nr_cfgs; i++) { 712f6fa56e2SRamesh Babu pconfig = &pipe->configs[i]; 713f6fa56e2SRamesh Babu if (in_fmt) 714f6fa56e2SRamesh Babu fmt = &pconfig->in_fmt; 715f6fa56e2SRamesh Babu else 716f6fa56e2SRamesh Babu fmt = &pconfig->out_fmt; 717f6fa56e2SRamesh Babu 718f6fa56e2SRamesh Babu if (CHECK_HW_PARAMS(params->ch, params->s_freq, params->s_fmt, 719f6fa56e2SRamesh Babu fmt->channels, fmt->freq, fmt->bps)) { 720f6fa56e2SRamesh Babu pipe->cur_config_idx = i; 721f6fa56e2SRamesh Babu pipe->memory_pages = pconfig->mem_pages; 722*bcc2a2dcSCezary Rojewski dev_dbg(skl->dev, "Using pipe config: %d\n", i); 723f6fa56e2SRamesh Babu 724f6fa56e2SRamesh Babu return 0; 725f6fa56e2SRamesh Babu } 726f6fa56e2SRamesh Babu } 727f6fa56e2SRamesh Babu 728*bcc2a2dcSCezary Rojewski dev_err(skl->dev, "Invalid pipe config: %d %d %d for pipe: %d\n", 729f6fa56e2SRamesh Babu params->ch, params->s_freq, params->s_fmt, pipe->ppl_id); 730f6fa56e2SRamesh Babu return -EINVAL; 731f6fa56e2SRamesh Babu } 732f6fa56e2SRamesh Babu 733f6fa56e2SRamesh Babu /* 734d93f8e55SVinod Koul * Mixer module represents a pipeline. So in the Pre-PMU event of mixer we 735d93f8e55SVinod Koul * need create the pipeline. So we do following: 736d93f8e55SVinod Koul * - check the resources 737d93f8e55SVinod Koul * - Create the pipeline 738d93f8e55SVinod Koul * - Initialize the modules in pipeline 739d93f8e55SVinod Koul * - finally bind all modules together 740d93f8e55SVinod Koul */ 741d93f8e55SVinod Koul static int skl_tplg_mixer_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w, 742*bcc2a2dcSCezary Rojewski struct skl_dev *skl) 743d93f8e55SVinod Koul { 744d93f8e55SVinod Koul int ret; 745d93f8e55SVinod Koul struct skl_module_cfg *mconfig = w->priv; 746d93f8e55SVinod Koul struct skl_pipe_module *w_module; 747d93f8e55SVinod Koul struct skl_pipe *s_pipe = mconfig->pipe; 748b8c722ddSJeeja KP struct skl_module_cfg *src_module = NULL, *dst_module, *module; 749b8c722ddSJeeja KP struct skl_module_deferred_bind *modules; 750d93f8e55SVinod Koul 751f6fa56e2SRamesh Babu ret = skl_tplg_get_pipe_config(skl, mconfig); 752f6fa56e2SRamesh Babu if (ret < 0) 753f6fa56e2SRamesh Babu return ret; 754f6fa56e2SRamesh Babu 755d93f8e55SVinod Koul /* check resource available */ 7569ba8ffefSDharageswari.R if (!skl_is_pipe_mcps_avail(skl, mconfig)) 757d93f8e55SVinod Koul return -EBUSY; 758d93f8e55SVinod Koul 7599ba8ffefSDharageswari.R if (!skl_is_pipe_mem_avail(skl, mconfig)) 760d93f8e55SVinod Koul return -ENOMEM; 761d93f8e55SVinod Koul 762d93f8e55SVinod Koul /* 763d93f8e55SVinod Koul * Create a list of modules for pipe. 764d93f8e55SVinod Koul * This list contains modules from source to sink 765d93f8e55SVinod Koul */ 766*bcc2a2dcSCezary Rojewski ret = skl_create_pipeline(skl, mconfig->pipe); 767d93f8e55SVinod Koul if (ret < 0) 768d93f8e55SVinod Koul return ret; 769d93f8e55SVinod Koul 770260eb73aSDharageswari R skl_tplg_alloc_pipe_mem(skl, mconfig); 771260eb73aSDharageswari R skl_tplg_alloc_pipe_mcps(skl, mconfig); 772d93f8e55SVinod Koul 773d93f8e55SVinod Koul /* Init all pipe modules from source to sink */ 774d93f8e55SVinod Koul ret = skl_tplg_init_pipe_modules(skl, s_pipe); 775d93f8e55SVinod Koul if (ret < 0) 776d93f8e55SVinod Koul return ret; 777d93f8e55SVinod Koul 778d93f8e55SVinod Koul /* Bind modules from source to sink */ 779d93f8e55SVinod Koul list_for_each_entry(w_module, &s_pipe->w_list, node) { 780d93f8e55SVinod Koul dst_module = w_module->w->priv; 781d93f8e55SVinod Koul 782d93f8e55SVinod Koul if (src_module == NULL) { 783d93f8e55SVinod Koul src_module = dst_module; 784d93f8e55SVinod Koul continue; 785d93f8e55SVinod Koul } 786d93f8e55SVinod Koul 787*bcc2a2dcSCezary Rojewski ret = skl_bind_modules(skl, src_module, dst_module); 788d93f8e55SVinod Koul if (ret < 0) 789d93f8e55SVinod Koul return ret; 790d93f8e55SVinod Koul 791d93f8e55SVinod Koul src_module = dst_module; 792d93f8e55SVinod Koul } 793d93f8e55SVinod Koul 794b8c722ddSJeeja KP /* 795b8c722ddSJeeja KP * When the destination module is initialized, check for these modules 796b8c722ddSJeeja KP * in deferred bind list. If found, bind them. 797b8c722ddSJeeja KP */ 798b8c722ddSJeeja KP list_for_each_entry(w_module, &s_pipe->w_list, node) { 799b8c722ddSJeeja KP if (list_empty(&skl->bind_list)) 800b8c722ddSJeeja KP break; 801b8c722ddSJeeja KP 802b8c722ddSJeeja KP list_for_each_entry(modules, &skl->bind_list, node) { 803b8c722ddSJeeja KP module = w_module->w->priv; 804b8c722ddSJeeja KP if (modules->dst == module) 805*bcc2a2dcSCezary Rojewski skl_bind_modules(skl, modules->src, 806b8c722ddSJeeja KP modules->dst); 807b8c722ddSJeeja KP } 808b8c722ddSJeeja KP } 809b8c722ddSJeeja KP 810d93f8e55SVinod Koul return 0; 811d93f8e55SVinod Koul } 812d93f8e55SVinod Koul 813*bcc2a2dcSCezary Rojewski static int skl_fill_sink_instance_id(struct skl_dev *skl, u32 *params, 814bf3e5ef5SDharageswari R int size, struct skl_module_cfg *mcfg) 8155e8f0ee4SDharageswari R { 8165e8f0ee4SDharageswari R int i, pvt_id; 8175e8f0ee4SDharageswari R 818bf3e5ef5SDharageswari R if (mcfg->m_type == SKL_MODULE_TYPE_KPB) { 819bf3e5ef5SDharageswari R struct skl_kpb_params *kpb_params = 820bf3e5ef5SDharageswari R (struct skl_kpb_params *)params; 821f7a9f772SSriram Periyasamy struct skl_mod_inst_map *inst = kpb_params->u.map; 8225e8f0ee4SDharageswari R 823bf3e5ef5SDharageswari R for (i = 0; i < kpb_params->num_modules; i++) { 824*bcc2a2dcSCezary Rojewski pvt_id = skl_get_pvt_instance_id_map(skl, inst->mod_id, 825bf3e5ef5SDharageswari R inst->inst_id); 8265e8f0ee4SDharageswari R if (pvt_id < 0) 8275e8f0ee4SDharageswari R return -EINVAL; 828bf3e5ef5SDharageswari R 8295e8f0ee4SDharageswari R inst->inst_id = pvt_id; 8305e8f0ee4SDharageswari R inst++; 8315e8f0ee4SDharageswari R } 8325e8f0ee4SDharageswari R } 8335e8f0ee4SDharageswari R 834bf3e5ef5SDharageswari R return 0; 835bf3e5ef5SDharageswari R } 836cc6a4044SJeeja KP /* 837cc6a4044SJeeja KP * Some modules require params to be set after the module is bound to 838cc6a4044SJeeja KP * all pins connected. 839cc6a4044SJeeja KP * 840cc6a4044SJeeja KP * The module provider initializes set_param flag for such modules and we 841cc6a4044SJeeja KP * send params after binding 842cc6a4044SJeeja KP */ 843cc6a4044SJeeja KP static int skl_tplg_set_module_bind_params(struct snd_soc_dapm_widget *w, 844*bcc2a2dcSCezary Rojewski struct skl_module_cfg *mcfg, struct skl_dev *skl) 845cc6a4044SJeeja KP { 846cc6a4044SJeeja KP int i, ret; 847cc6a4044SJeeja KP struct skl_module_cfg *mconfig = w->priv; 848cc6a4044SJeeja KP const struct snd_kcontrol_new *k; 849cc6a4044SJeeja KP struct soc_bytes_ext *sb; 850cc6a4044SJeeja KP struct skl_algo_data *bc; 851cc6a4044SJeeja KP struct skl_specific_cfg *sp_cfg; 852bf3e5ef5SDharageswari R u32 *params; 853cc6a4044SJeeja KP 854cc6a4044SJeeja KP /* 855cc6a4044SJeeja KP * check all out/in pins are in bind state. 856cc6a4044SJeeja KP * if so set the module param 857cc6a4044SJeeja KP */ 858f6fa56e2SRamesh Babu for (i = 0; i < mcfg->module->max_output_pins; i++) { 859cc6a4044SJeeja KP if (mcfg->m_out_pin[i].pin_state != SKL_PIN_BIND_DONE) 860cc6a4044SJeeja KP return 0; 861cc6a4044SJeeja KP } 862cc6a4044SJeeja KP 863f6fa56e2SRamesh Babu for (i = 0; i < mcfg->module->max_input_pins; i++) { 864cc6a4044SJeeja KP if (mcfg->m_in_pin[i].pin_state != SKL_PIN_BIND_DONE) 865cc6a4044SJeeja KP return 0; 866cc6a4044SJeeja KP } 867cc6a4044SJeeja KP 868cc6a4044SJeeja KP if (mconfig->formats_config.caps_size > 0 && 869cc6a4044SJeeja KP mconfig->formats_config.set_params == SKL_PARAM_BIND) { 870cc6a4044SJeeja KP sp_cfg = &mconfig->formats_config; 871*bcc2a2dcSCezary Rojewski ret = skl_set_module_params(skl, sp_cfg->caps, 872cc6a4044SJeeja KP sp_cfg->caps_size, 873cc6a4044SJeeja KP sp_cfg->param_id, mconfig); 874cc6a4044SJeeja KP if (ret < 0) 875cc6a4044SJeeja KP return ret; 876cc6a4044SJeeja KP } 877cc6a4044SJeeja KP 878cc6a4044SJeeja KP for (i = 0; i < w->num_kcontrols; i++) { 879cc6a4044SJeeja KP k = &w->kcontrol_news[i]; 880cc6a4044SJeeja KP if (k->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { 881cc6a4044SJeeja KP sb = (void *) k->private_value; 882cc6a4044SJeeja KP bc = (struct skl_algo_data *)sb->dobj.private; 883cc6a4044SJeeja KP 884cc6a4044SJeeja KP if (bc->set_params == SKL_PARAM_BIND) { 885ca92cc46Szhong jiang params = kmemdup(bc->params, bc->max, GFP_KERNEL); 886bf3e5ef5SDharageswari R if (!params) 887bf3e5ef5SDharageswari R return -ENOMEM; 888bf3e5ef5SDharageswari R 889*bcc2a2dcSCezary Rojewski skl_fill_sink_instance_id(skl, params, bc->max, 890bf3e5ef5SDharageswari R mconfig); 891bf3e5ef5SDharageswari R 892*bcc2a2dcSCezary Rojewski ret = skl_set_module_params(skl, params, 893bf3e5ef5SDharageswari R bc->max, bc->param_id, mconfig); 894bf3e5ef5SDharageswari R kfree(params); 895bf3e5ef5SDharageswari R 896cc6a4044SJeeja KP if (ret < 0) 897cc6a4044SJeeja KP return ret; 898cc6a4044SJeeja KP } 899cc6a4044SJeeja KP } 900cc6a4044SJeeja KP } 901cc6a4044SJeeja KP 902cc6a4044SJeeja KP return 0; 903cc6a4044SJeeja KP } 904cc6a4044SJeeja KP 905*bcc2a2dcSCezary Rojewski static int skl_get_module_id(struct skl_dev *skl, guid_t *uuid) 906f7a9f772SSriram Periyasamy { 907f7a9f772SSriram Periyasamy struct uuid_module *module; 908f7a9f772SSriram Periyasamy 909*bcc2a2dcSCezary Rojewski list_for_each_entry(module, &skl->uuid_list, list) { 9109e0784d0SAndy Shevchenko if (guid_equal(uuid, &module->uuid)) 911f7a9f772SSriram Periyasamy return module->id; 912f7a9f772SSriram Periyasamy } 913f7a9f772SSriram Periyasamy 914f7a9f772SSriram Periyasamy return -EINVAL; 915f7a9f772SSriram Periyasamy } 916f7a9f772SSriram Periyasamy 917*bcc2a2dcSCezary Rojewski static int skl_tplg_find_moduleid_from_uuid(struct skl_dev *skl, 918f7a9f772SSriram Periyasamy const struct snd_kcontrol_new *k) 919f7a9f772SSriram Periyasamy { 920f7a9f772SSriram Periyasamy struct soc_bytes_ext *sb = (void *) k->private_value; 921f7a9f772SSriram Periyasamy struct skl_algo_data *bc = (struct skl_algo_data *)sb->dobj.private; 922f7a9f772SSriram Periyasamy struct skl_kpb_params *uuid_params, *params; 92376f56faeSRakesh Ughreja struct hdac_bus *bus = skl_to_bus(skl); 924f7a9f772SSriram Periyasamy int i, size, module_id; 925f7a9f772SSriram Periyasamy 926f7a9f772SSriram Periyasamy if (bc->set_params == SKL_PARAM_BIND && bc->max) { 927f7a9f772SSriram Periyasamy uuid_params = (struct skl_kpb_params *)bc->params; 928d00cc2f1SGustavo A. R. Silva size = struct_size(params, u.map, uuid_params->num_modules); 929f7a9f772SSriram Periyasamy 930f7a9f772SSriram Periyasamy params = devm_kzalloc(bus->dev, size, GFP_KERNEL); 931f7a9f772SSriram Periyasamy if (!params) 932f7a9f772SSriram Periyasamy return -ENOMEM; 933f7a9f772SSriram Periyasamy 934f7a9f772SSriram Periyasamy params->num_modules = uuid_params->num_modules; 935f7a9f772SSriram Periyasamy 936f7a9f772SSriram Periyasamy for (i = 0; i < uuid_params->num_modules; i++) { 937*bcc2a2dcSCezary Rojewski module_id = skl_get_module_id(skl, 938f7a9f772SSriram Periyasamy &uuid_params->u.map_uuid[i].mod_uuid); 939f7a9f772SSriram Periyasamy if (module_id < 0) { 940f7a9f772SSriram Periyasamy devm_kfree(bus->dev, params); 941f7a9f772SSriram Periyasamy return -EINVAL; 942f7a9f772SSriram Periyasamy } 943f7a9f772SSriram Periyasamy 944f7a9f772SSriram Periyasamy params->u.map[i].mod_id = module_id; 945f7a9f772SSriram Periyasamy params->u.map[i].inst_id = 946f7a9f772SSriram Periyasamy uuid_params->u.map_uuid[i].inst_id; 947f7a9f772SSriram Periyasamy } 948f7a9f772SSriram Periyasamy 949f7a9f772SSriram Periyasamy devm_kfree(bus->dev, bc->params); 950f7a9f772SSriram Periyasamy bc->params = (char *)params; 951f7a9f772SSriram Periyasamy bc->max = size; 952f7a9f772SSriram Periyasamy } 953f7a9f772SSriram Periyasamy 954f7a9f772SSriram Periyasamy return 0; 955f7a9f772SSriram Periyasamy } 956f7a9f772SSriram Periyasamy 957f7a9f772SSriram Periyasamy /* 958f7a9f772SSriram Periyasamy * Retrieve the module id from UUID mentioned in the 959f7a9f772SSriram Periyasamy * post bind params 960f7a9f772SSriram Periyasamy */ 961*bcc2a2dcSCezary Rojewski void skl_tplg_add_moduleid_in_bind_params(struct skl_dev *skl, 962f7a9f772SSriram Periyasamy struct snd_soc_dapm_widget *w) 963f7a9f772SSriram Periyasamy { 964f7a9f772SSriram Periyasamy struct skl_module_cfg *mconfig = w->priv; 965f7a9f772SSriram Periyasamy int i; 966f7a9f772SSriram Periyasamy 967f7a9f772SSriram Periyasamy /* 968f7a9f772SSriram Periyasamy * Post bind params are used for only for KPB 969f7a9f772SSriram Periyasamy * to set copier instances to drain the data 970f7a9f772SSriram Periyasamy * in fast mode 971f7a9f772SSriram Periyasamy */ 972f7a9f772SSriram Periyasamy if (mconfig->m_type != SKL_MODULE_TYPE_KPB) 973f7a9f772SSriram Periyasamy return; 974f7a9f772SSriram Periyasamy 975f7a9f772SSriram Periyasamy for (i = 0; i < w->num_kcontrols; i++) 976f7a9f772SSriram Periyasamy if ((w->kcontrol_news[i].access & 977f7a9f772SSriram Periyasamy SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) && 978f7a9f772SSriram Periyasamy (skl_tplg_find_moduleid_from_uuid(skl, 979f7a9f772SSriram Periyasamy &w->kcontrol_news[i]) < 0)) 980*bcc2a2dcSCezary Rojewski dev_err(skl->dev, 981f7a9f772SSriram Periyasamy "%s: invalid kpb post bind params\n", 982f7a9f772SSriram Periyasamy __func__); 983f7a9f772SSriram Periyasamy } 984b8c722ddSJeeja KP 985*bcc2a2dcSCezary Rojewski static int skl_tplg_module_add_deferred_bind(struct skl_dev *skl, 986b8c722ddSJeeja KP struct skl_module_cfg *src, struct skl_module_cfg *dst) 987b8c722ddSJeeja KP { 988b8c722ddSJeeja KP struct skl_module_deferred_bind *m_list, *modules; 989b8c722ddSJeeja KP int i; 990b8c722ddSJeeja KP 991b8c722ddSJeeja KP /* only supported for module with static pin connection */ 992f6fa56e2SRamesh Babu for (i = 0; i < dst->module->max_input_pins; i++) { 993b8c722ddSJeeja KP struct skl_module_pin *pin = &dst->m_in_pin[i]; 994b8c722ddSJeeja KP 995b8c722ddSJeeja KP if (pin->is_dynamic) 996b8c722ddSJeeja KP continue; 997b8c722ddSJeeja KP 998b8c722ddSJeeja KP if ((pin->id.module_id == src->id.module_id) && 999b8c722ddSJeeja KP (pin->id.instance_id == src->id.instance_id)) { 1000b8c722ddSJeeja KP 1001b8c722ddSJeeja KP if (!list_empty(&skl->bind_list)) { 1002b8c722ddSJeeja KP list_for_each_entry(modules, &skl->bind_list, node) { 1003b8c722ddSJeeja KP if (modules->src == src && modules->dst == dst) 1004b8c722ddSJeeja KP return 0; 1005b8c722ddSJeeja KP } 1006b8c722ddSJeeja KP } 1007b8c722ddSJeeja KP 1008b8c722ddSJeeja KP m_list = kzalloc(sizeof(*m_list), GFP_KERNEL); 1009b8c722ddSJeeja KP if (!m_list) 1010b8c722ddSJeeja KP return -ENOMEM; 1011b8c722ddSJeeja KP 1012b8c722ddSJeeja KP m_list->src = src; 1013b8c722ddSJeeja KP m_list->dst = dst; 1014b8c722ddSJeeja KP 1015b8c722ddSJeeja KP list_add(&m_list->node, &skl->bind_list); 1016b8c722ddSJeeja KP } 1017b8c722ddSJeeja KP } 1018b8c722ddSJeeja KP 1019b8c722ddSJeeja KP return 0; 1020b8c722ddSJeeja KP } 1021b8c722ddSJeeja KP 10228724ff17SJeeja KP static int skl_tplg_bind_sinks(struct snd_soc_dapm_widget *w, 1023*bcc2a2dcSCezary Rojewski struct skl_dev *skl, 10246bd4cf85SJeeja KP struct snd_soc_dapm_widget *src_w, 10258724ff17SJeeja KP struct skl_module_cfg *src_mconfig) 1026d93f8e55SVinod Koul { 1027d93f8e55SVinod Koul struct snd_soc_dapm_path *p; 10280ed95d76SJeeja KP struct snd_soc_dapm_widget *sink = NULL, *next_sink = NULL; 10298724ff17SJeeja KP struct skl_module_cfg *sink_mconfig; 10308724ff17SJeeja KP int ret; 1031d93f8e55SVinod Koul 10328724ff17SJeeja KP snd_soc_dapm_widget_for_each_sink_path(w, p) { 1033d93f8e55SVinod Koul if (!p->connect) 1034d93f8e55SVinod Koul continue; 1035d93f8e55SVinod Koul 1036*bcc2a2dcSCezary Rojewski dev_dbg(skl->dev, 1037*bcc2a2dcSCezary Rojewski "%s: src widget=%s\n", __func__, w->name); 1038*bcc2a2dcSCezary Rojewski dev_dbg(skl->dev, 1039*bcc2a2dcSCezary Rojewski "%s: sink widget=%s\n", __func__, p->sink->name); 1040d93f8e55SVinod Koul 10410ed95d76SJeeja KP next_sink = p->sink; 10426bd4cf85SJeeja KP 1043*bcc2a2dcSCezary Rojewski if (!is_skl_dsp_widget_type(p->sink, skl->dev)) 10446bd4cf85SJeeja KP return skl_tplg_bind_sinks(p->sink, skl, src_w, src_mconfig); 10456bd4cf85SJeeja KP 1046d93f8e55SVinod Koul /* 1047d93f8e55SVinod Koul * here we will check widgets in sink pipelines, so that 1048d93f8e55SVinod Koul * can be any widgets type and we are only interested if 1049d93f8e55SVinod Koul * they are ones used for SKL so check that first 1050d93f8e55SVinod Koul */ 1051d93f8e55SVinod Koul if ((p->sink->priv != NULL) && 1052*bcc2a2dcSCezary Rojewski is_skl_dsp_widget_type(p->sink, skl->dev)) { 1053d93f8e55SVinod Koul 1054d93f8e55SVinod Koul sink = p->sink; 1055d93f8e55SVinod Koul sink_mconfig = sink->priv; 1056d93f8e55SVinod Koul 1057b8c722ddSJeeja KP /* 1058b8c722ddSJeeja KP * Modules other than PGA leaf can be connected 1059b8c722ddSJeeja KP * directly or via switch to a module in another 1060b8c722ddSJeeja KP * pipeline. EX: reference path 1061b8c722ddSJeeja KP * when the path is enabled, the dst module that needs 1062b8c722ddSJeeja KP * to be bound may not be initialized. if the module is 1063b8c722ddSJeeja KP * not initialized, add these modules in the deferred 1064b8c722ddSJeeja KP * bind list and when the dst module is initialised, 1065b8c722ddSJeeja KP * bind this module to the dst_module in deferred list. 1066b8c722ddSJeeja KP */ 1067b8c722ddSJeeja KP if (((src_mconfig->m_state == SKL_MODULE_INIT_DONE) 1068b8c722ddSJeeja KP && (sink_mconfig->m_state == SKL_MODULE_UNINIT))) { 1069b8c722ddSJeeja KP 1070b8c722ddSJeeja KP ret = skl_tplg_module_add_deferred_bind(skl, 1071b8c722ddSJeeja KP src_mconfig, sink_mconfig); 1072b8c722ddSJeeja KP 1073b8c722ddSJeeja KP if (ret < 0) 1074b8c722ddSJeeja KP return ret; 1075b8c722ddSJeeja KP 1076b8c722ddSJeeja KP } 1077b8c722ddSJeeja KP 1078b8c722ddSJeeja KP 1079cc6a4044SJeeja KP if (src_mconfig->m_state == SKL_MODULE_UNINIT || 1080cc6a4044SJeeja KP sink_mconfig->m_state == SKL_MODULE_UNINIT) 1081cc6a4044SJeeja KP continue; 1082cc6a4044SJeeja KP 1083d93f8e55SVinod Koul /* Bind source to sink, mixin is always source */ 1084*bcc2a2dcSCezary Rojewski ret = skl_bind_modules(skl, src_mconfig, sink_mconfig); 1085d93f8e55SVinod Koul if (ret) 1086d93f8e55SVinod Koul return ret; 1087d93f8e55SVinod Koul 1088cc6a4044SJeeja KP /* set module params after bind */ 1089*bcc2a2dcSCezary Rojewski skl_tplg_set_module_bind_params(src_w, 1090*bcc2a2dcSCezary Rojewski src_mconfig, skl); 1091*bcc2a2dcSCezary Rojewski skl_tplg_set_module_bind_params(sink, 1092*bcc2a2dcSCezary Rojewski sink_mconfig, skl); 1093cc6a4044SJeeja KP 1094d93f8e55SVinod Koul /* Start sinks pipe first */ 1095d93f8e55SVinod Koul if (sink_mconfig->pipe->state != SKL_PIPE_STARTED) { 1096d1730c3dSJeeja KP if (sink_mconfig->pipe->conn_type != 1097d1730c3dSJeeja KP SKL_PIPE_CONN_TYPE_FE) 1098*bcc2a2dcSCezary Rojewski ret = skl_run_pipe(skl, 1099d1730c3dSJeeja KP sink_mconfig->pipe); 1100d93f8e55SVinod Koul if (ret) 1101d93f8e55SVinod Koul return ret; 1102d93f8e55SVinod Koul } 1103d93f8e55SVinod Koul } 1104d93f8e55SVinod Koul } 1105d93f8e55SVinod Koul 110610a5439fSguneshwor.o.singh@intel.com if (!sink && next_sink) 11076bd4cf85SJeeja KP return skl_tplg_bind_sinks(next_sink, skl, src_w, src_mconfig); 11088724ff17SJeeja KP 11098724ff17SJeeja KP return 0; 11108724ff17SJeeja KP } 11118724ff17SJeeja KP 1112d93f8e55SVinod Koul /* 1113d93f8e55SVinod Koul * A PGA represents a module in a pipeline. So in the Pre-PMU event of PGA 1114d93f8e55SVinod Koul * we need to do following: 1115d93f8e55SVinod Koul * - Bind to sink pipeline 1116d93f8e55SVinod Koul * Since the sink pipes can be running and we don't get mixer event on 1117d93f8e55SVinod Koul * connect for already running mixer, we need to find the sink pipes 1118d93f8e55SVinod Koul * here and bind to them. This way dynamic connect works. 1119d93f8e55SVinod Koul * - Start sink pipeline, if not running 1120d93f8e55SVinod Koul * - Then run current pipe 1121d93f8e55SVinod Koul */ 1122d93f8e55SVinod Koul static int skl_tplg_pga_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w, 1123*bcc2a2dcSCezary Rojewski struct skl_dev *skl) 1124d93f8e55SVinod Koul { 11258724ff17SJeeja KP struct skl_module_cfg *src_mconfig; 1126d93f8e55SVinod Koul int ret = 0; 1127d93f8e55SVinod Koul 11288724ff17SJeeja KP src_mconfig = w->priv; 1129d93f8e55SVinod Koul 1130d93f8e55SVinod Koul /* 1131d93f8e55SVinod Koul * find which sink it is connected to, bind with the sink, 1132d93f8e55SVinod Koul * if sink is not started, start sink pipe first, then start 1133d93f8e55SVinod Koul * this pipe 1134d93f8e55SVinod Koul */ 11356bd4cf85SJeeja KP ret = skl_tplg_bind_sinks(w, skl, w, src_mconfig); 11368724ff17SJeeja KP if (ret) 11378724ff17SJeeja KP return ret; 11388724ff17SJeeja KP 1139d93f8e55SVinod Koul /* Start source pipe last after starting all sinks */ 1140d1730c3dSJeeja KP if (src_mconfig->pipe->conn_type != SKL_PIPE_CONN_TYPE_FE) 1141*bcc2a2dcSCezary Rojewski return skl_run_pipe(skl, src_mconfig->pipe); 1142d93f8e55SVinod Koul 1143d93f8e55SVinod Koul return 0; 1144d93f8e55SVinod Koul } 1145d93f8e55SVinod Koul 11468724ff17SJeeja KP static struct snd_soc_dapm_widget *skl_get_src_dsp_widget( 1147*bcc2a2dcSCezary Rojewski struct snd_soc_dapm_widget *w, struct skl_dev *skl) 11488724ff17SJeeja KP { 11498724ff17SJeeja KP struct snd_soc_dapm_path *p; 11508724ff17SJeeja KP struct snd_soc_dapm_widget *src_w = NULL; 11518724ff17SJeeja KP 1152d93f8e55SVinod Koul snd_soc_dapm_widget_for_each_source_path(w, p) { 11538724ff17SJeeja KP src_w = p->source; 1154d93f8e55SVinod Koul if (!p->connect) 1155d93f8e55SVinod Koul continue; 1156d93f8e55SVinod Koul 1157*bcc2a2dcSCezary Rojewski dev_dbg(skl->dev, "sink widget=%s\n", w->name); 1158*bcc2a2dcSCezary Rojewski dev_dbg(skl->dev, "src widget=%s\n", p->source->name); 1159d93f8e55SVinod Koul 1160d93f8e55SVinod Koul /* 11618724ff17SJeeja KP * here we will check widgets in sink pipelines, so that can 11628724ff17SJeeja KP * be any widgets type and we are only interested if they are 11638724ff17SJeeja KP * ones used for SKL so check that first 1164d93f8e55SVinod Koul */ 11658724ff17SJeeja KP if ((p->source->priv != NULL) && 1166*bcc2a2dcSCezary Rojewski is_skl_dsp_widget_type(p->source, skl->dev)) { 11678724ff17SJeeja KP return p->source; 1168d93f8e55SVinod Koul } 1169d93f8e55SVinod Koul } 1170d93f8e55SVinod Koul 11718724ff17SJeeja KP if (src_w != NULL) 11728724ff17SJeeja KP return skl_get_src_dsp_widget(src_w, skl); 1173d93f8e55SVinod Koul 11748724ff17SJeeja KP return NULL; 1175d93f8e55SVinod Koul } 1176d93f8e55SVinod Koul 1177d93f8e55SVinod Koul /* 1178d93f8e55SVinod Koul * in the Post-PMU event of mixer we need to do following: 1179d93f8e55SVinod Koul * - Check if this pipe is running 1180d93f8e55SVinod Koul * - if not, then 1181d93f8e55SVinod Koul * - bind this pipeline to its source pipeline 1182d93f8e55SVinod Koul * if source pipe is already running, this means it is a dynamic 1183d93f8e55SVinod Koul * connection and we need to bind only to that pipe 1184d93f8e55SVinod Koul * - start this pipeline 1185d93f8e55SVinod Koul */ 1186d93f8e55SVinod Koul static int skl_tplg_mixer_dapm_post_pmu_event(struct snd_soc_dapm_widget *w, 1187*bcc2a2dcSCezary Rojewski struct skl_dev *skl) 1188d93f8e55SVinod Koul { 1189d93f8e55SVinod Koul int ret = 0; 1190d93f8e55SVinod Koul struct snd_soc_dapm_widget *source, *sink; 1191d93f8e55SVinod Koul struct skl_module_cfg *src_mconfig, *sink_mconfig; 1192d93f8e55SVinod Koul int src_pipe_started = 0; 1193d93f8e55SVinod Koul 1194d93f8e55SVinod Koul sink = w; 1195d93f8e55SVinod Koul sink_mconfig = sink->priv; 1196d93f8e55SVinod Koul 1197d93f8e55SVinod Koul /* 1198d93f8e55SVinod Koul * If source pipe is already started, that means source is driving 1199d93f8e55SVinod Koul * one more sink before this sink got connected, Since source is 1200d93f8e55SVinod Koul * started, bind this sink to source and start this pipe. 1201d93f8e55SVinod Koul */ 12028724ff17SJeeja KP source = skl_get_src_dsp_widget(w, skl); 12038724ff17SJeeja KP if (source != NULL) { 1204d93f8e55SVinod Koul src_mconfig = source->priv; 1205d93f8e55SVinod Koul sink_mconfig = sink->priv; 1206d93f8e55SVinod Koul src_pipe_started = 1; 1207d93f8e55SVinod Koul 1208d93f8e55SVinod Koul /* 12098724ff17SJeeja KP * check pipe state, then no need to bind or start the 12108724ff17SJeeja KP * pipe 1211d93f8e55SVinod Koul */ 1212d93f8e55SVinod Koul if (src_mconfig->pipe->state != SKL_PIPE_STARTED) 1213d93f8e55SVinod Koul src_pipe_started = 0; 1214d93f8e55SVinod Koul } 1215d93f8e55SVinod Koul 1216d93f8e55SVinod Koul if (src_pipe_started) { 1217*bcc2a2dcSCezary Rojewski ret = skl_bind_modules(skl, src_mconfig, sink_mconfig); 1218d93f8e55SVinod Koul if (ret) 1219d93f8e55SVinod Koul return ret; 1220d93f8e55SVinod Koul 1221cc6a4044SJeeja KP /* set module params after bind */ 1222*bcc2a2dcSCezary Rojewski skl_tplg_set_module_bind_params(source, src_mconfig, skl); 1223*bcc2a2dcSCezary Rojewski skl_tplg_set_module_bind_params(sink, sink_mconfig, skl); 1224cc6a4044SJeeja KP 1225d1730c3dSJeeja KP if (sink_mconfig->pipe->conn_type != SKL_PIPE_CONN_TYPE_FE) 1226*bcc2a2dcSCezary Rojewski ret = skl_run_pipe(skl, sink_mconfig->pipe); 1227d93f8e55SVinod Koul } 1228d93f8e55SVinod Koul 1229d93f8e55SVinod Koul return ret; 1230d93f8e55SVinod Koul } 1231d93f8e55SVinod Koul 1232d93f8e55SVinod Koul /* 1233d93f8e55SVinod Koul * in the Pre-PMD event of mixer we need to do following: 1234d93f8e55SVinod Koul * - Stop the pipe 1235d93f8e55SVinod Koul * - find the source connections and remove that from dapm_path_list 1236d93f8e55SVinod Koul * - unbind with source pipelines if still connected 1237d93f8e55SVinod Koul */ 1238d93f8e55SVinod Koul static int skl_tplg_mixer_dapm_pre_pmd_event(struct snd_soc_dapm_widget *w, 1239*bcc2a2dcSCezary Rojewski struct skl_dev *skl) 1240d93f8e55SVinod Koul { 1241d93f8e55SVinod Koul struct skl_module_cfg *src_mconfig, *sink_mconfig; 1242ce1b5551SJeeja KP int ret = 0, i; 1243d93f8e55SVinod Koul 1244ce1b5551SJeeja KP sink_mconfig = w->priv; 1245d93f8e55SVinod Koul 1246d93f8e55SVinod Koul /* Stop the pipe */ 1247*bcc2a2dcSCezary Rojewski ret = skl_stop_pipe(skl, sink_mconfig->pipe); 1248d93f8e55SVinod Koul if (ret) 1249d93f8e55SVinod Koul return ret; 1250d93f8e55SVinod Koul 1251f6fa56e2SRamesh Babu for (i = 0; i < sink_mconfig->module->max_input_pins; i++) { 1252ce1b5551SJeeja KP if (sink_mconfig->m_in_pin[i].pin_state == SKL_PIN_BIND_DONE) { 1253ce1b5551SJeeja KP src_mconfig = sink_mconfig->m_in_pin[i].tgt_mcfg; 1254ce1b5551SJeeja KP if (!src_mconfig) 1255ce1b5551SJeeja KP continue; 1256d93f8e55SVinod Koul 1257*bcc2a2dcSCezary Rojewski ret = skl_unbind_modules(skl, 1258ce1b5551SJeeja KP src_mconfig, sink_mconfig); 1259ce1b5551SJeeja KP } 1260d93f8e55SVinod Koul } 1261d93f8e55SVinod Koul 1262d93f8e55SVinod Koul return ret; 1263d93f8e55SVinod Koul } 1264d93f8e55SVinod Koul 1265d93f8e55SVinod Koul /* 1266d93f8e55SVinod Koul * in the Post-PMD event of mixer we need to do following: 1267d93f8e55SVinod Koul * - Free the mcps used 1268d93f8e55SVinod Koul * - Free the mem used 1269d93f8e55SVinod Koul * - Unbind the modules within the pipeline 1270d93f8e55SVinod Koul * - Delete the pipeline (modules are not required to be explicitly 1271d93f8e55SVinod Koul * deleted, pipeline delete is enough here 1272d93f8e55SVinod Koul */ 1273d93f8e55SVinod Koul static int skl_tplg_mixer_dapm_post_pmd_event(struct snd_soc_dapm_widget *w, 1274*bcc2a2dcSCezary Rojewski struct skl_dev *skl) 1275d93f8e55SVinod Koul { 1276d93f8e55SVinod Koul struct skl_module_cfg *mconfig = w->priv; 1277d93f8e55SVinod Koul struct skl_pipe_module *w_module; 1278d93f8e55SVinod Koul struct skl_module_cfg *src_module = NULL, *dst_module; 1279d93f8e55SVinod Koul struct skl_pipe *s_pipe = mconfig->pipe; 1280550b349aSDan Carpenter struct skl_module_deferred_bind *modules, *tmp; 1281d93f8e55SVinod Koul 1282260eb73aSDharageswari R if (s_pipe->state == SKL_PIPE_INVALID) 1283260eb73aSDharageswari R return -EINVAL; 1284260eb73aSDharageswari R 1285d93f8e55SVinod Koul skl_tplg_free_pipe_mcps(skl, mconfig); 128665976878SVinod Koul skl_tplg_free_pipe_mem(skl, mconfig); 1287d93f8e55SVinod Koul 1288d93f8e55SVinod Koul list_for_each_entry(w_module, &s_pipe->w_list, node) { 1289b8c722ddSJeeja KP if (list_empty(&skl->bind_list)) 1290b8c722ddSJeeja KP break; 1291b8c722ddSJeeja KP 1292b8c722ddSJeeja KP src_module = w_module->w->priv; 1293b8c722ddSJeeja KP 1294550b349aSDan Carpenter list_for_each_entry_safe(modules, tmp, &skl->bind_list, node) { 1295b8c722ddSJeeja KP /* 1296b8c722ddSJeeja KP * When the destination module is deleted, Unbind the 1297b8c722ddSJeeja KP * modules from deferred bind list. 1298b8c722ddSJeeja KP */ 1299b8c722ddSJeeja KP if (modules->dst == src_module) { 1300*bcc2a2dcSCezary Rojewski skl_unbind_modules(skl, modules->src, 1301b8c722ddSJeeja KP modules->dst); 1302b8c722ddSJeeja KP } 1303b8c722ddSJeeja KP 1304b8c722ddSJeeja KP /* 1305b8c722ddSJeeja KP * When the source module is deleted, remove this entry 1306b8c722ddSJeeja KP * from the deferred bind list. 1307b8c722ddSJeeja KP */ 1308b8c722ddSJeeja KP if (modules->src == src_module) { 1309b8c722ddSJeeja KP list_del(&modules->node); 1310b8c722ddSJeeja KP modules->src = NULL; 1311b8c722ddSJeeja KP modules->dst = NULL; 1312b8c722ddSJeeja KP kfree(modules); 1313b8c722ddSJeeja KP } 1314b8c722ddSJeeja KP } 1315b8c722ddSJeeja KP } 1316b8c722ddSJeeja KP 1317b8c722ddSJeeja KP list_for_each_entry(w_module, &s_pipe->w_list, node) { 1318d93f8e55SVinod Koul dst_module = w_module->w->priv; 1319d93f8e55SVinod Koul 1320260eb73aSDharageswari R if (mconfig->m_state >= SKL_MODULE_INIT_DONE) 13217ae3cb15SVinod Koul skl_tplg_free_pipe_mcps(skl, dst_module); 1322d93f8e55SVinod Koul if (src_module == NULL) { 1323d93f8e55SVinod Koul src_module = dst_module; 1324d93f8e55SVinod Koul continue; 1325d93f8e55SVinod Koul } 1326d93f8e55SVinod Koul 1327*bcc2a2dcSCezary Rojewski skl_unbind_modules(skl, src_module, dst_module); 1328d93f8e55SVinod Koul src_module = dst_module; 1329d93f8e55SVinod Koul } 1330d93f8e55SVinod Koul 1331*bcc2a2dcSCezary Rojewski skl_delete_pipe(skl, mconfig->pipe); 1332d93f8e55SVinod Koul 1333473a4d51SJeeja KP list_for_each_entry(w_module, &s_pipe->w_list, node) { 1334473a4d51SJeeja KP src_module = w_module->w->priv; 1335473a4d51SJeeja KP src_module->m_state = SKL_MODULE_UNINIT; 1336473a4d51SJeeja KP } 1337473a4d51SJeeja KP 1338*bcc2a2dcSCezary Rojewski return skl_tplg_unload_pipe_modules(skl, s_pipe); 1339d93f8e55SVinod Koul } 1340d93f8e55SVinod Koul 1341d93f8e55SVinod Koul /* 1342d93f8e55SVinod Koul * in the Post-PMD event of PGA we need to do following: 1343d93f8e55SVinod Koul * - Free the mcps used 1344d93f8e55SVinod Koul * - Stop the pipeline 1345d93f8e55SVinod Koul * - In source pipe is connected, unbind with source pipelines 1346d93f8e55SVinod Koul */ 1347d93f8e55SVinod Koul static int skl_tplg_pga_dapm_post_pmd_event(struct snd_soc_dapm_widget *w, 1348*bcc2a2dcSCezary Rojewski struct skl_dev *skl) 1349d93f8e55SVinod Koul { 1350d93f8e55SVinod Koul struct skl_module_cfg *src_mconfig, *sink_mconfig; 1351ce1b5551SJeeja KP int ret = 0, i; 1352d93f8e55SVinod Koul 1353ce1b5551SJeeja KP src_mconfig = w->priv; 1354d93f8e55SVinod Koul 1355d93f8e55SVinod Koul /* Stop the pipe since this is a mixin module */ 1356*bcc2a2dcSCezary Rojewski ret = skl_stop_pipe(skl, src_mconfig->pipe); 1357d93f8e55SVinod Koul if (ret) 1358d93f8e55SVinod Koul return ret; 1359d93f8e55SVinod Koul 1360f6fa56e2SRamesh Babu for (i = 0; i < src_mconfig->module->max_output_pins; i++) { 1361ce1b5551SJeeja KP if (src_mconfig->m_out_pin[i].pin_state == SKL_PIN_BIND_DONE) { 1362ce1b5551SJeeja KP sink_mconfig = src_mconfig->m_out_pin[i].tgt_mcfg; 1363ce1b5551SJeeja KP if (!sink_mconfig) 1364ce1b5551SJeeja KP continue; 1365d93f8e55SVinod Koul /* 1366ce1b5551SJeeja KP * This is a connecter and if path is found that means 1367d93f8e55SVinod Koul * unbind between source and sink has not happened yet 1368d93f8e55SVinod Koul */ 1369*bcc2a2dcSCezary Rojewski ret = skl_unbind_modules(skl, src_mconfig, 1370ce1b5551SJeeja KP sink_mconfig); 1371ce1b5551SJeeja KP } 1372d93f8e55SVinod Koul } 1373d93f8e55SVinod Koul 1374d93f8e55SVinod Koul return ret; 1375d93f8e55SVinod Koul } 1376d93f8e55SVinod Koul 1377d93f8e55SVinod Koul /* 1378d93f8e55SVinod Koul * In modelling, we assume there will be ONLY one mixer in a pipeline. If a 1379d93f8e55SVinod Koul * second one is required that is created as another pipe entity. 1380d93f8e55SVinod Koul * The mixer is responsible for pipe management and represent a pipeline 1381d93f8e55SVinod Koul * instance 1382d93f8e55SVinod Koul */ 1383d93f8e55SVinod Koul static int skl_tplg_mixer_event(struct snd_soc_dapm_widget *w, 1384d93f8e55SVinod Koul struct snd_kcontrol *k, int event) 1385d93f8e55SVinod Koul { 1386d93f8e55SVinod Koul struct snd_soc_dapm_context *dapm = w->dapm; 1387*bcc2a2dcSCezary Rojewski struct skl_dev *skl = get_skl_ctx(dapm->dev); 1388d93f8e55SVinod Koul 1389d93f8e55SVinod Koul switch (event) { 1390d93f8e55SVinod Koul case SND_SOC_DAPM_PRE_PMU: 1391d93f8e55SVinod Koul return skl_tplg_mixer_dapm_pre_pmu_event(w, skl); 1392d93f8e55SVinod Koul 1393d93f8e55SVinod Koul case SND_SOC_DAPM_POST_PMU: 1394d93f8e55SVinod Koul return skl_tplg_mixer_dapm_post_pmu_event(w, skl); 1395d93f8e55SVinod Koul 1396d93f8e55SVinod Koul case SND_SOC_DAPM_PRE_PMD: 1397d93f8e55SVinod Koul return skl_tplg_mixer_dapm_pre_pmd_event(w, skl); 1398d93f8e55SVinod Koul 1399d93f8e55SVinod Koul case SND_SOC_DAPM_POST_PMD: 1400d93f8e55SVinod Koul return skl_tplg_mixer_dapm_post_pmd_event(w, skl); 1401d93f8e55SVinod Koul } 1402d93f8e55SVinod Koul 1403d93f8e55SVinod Koul return 0; 1404d93f8e55SVinod Koul } 1405d93f8e55SVinod Koul 1406d93f8e55SVinod Koul /* 1407d93f8e55SVinod Koul * In modelling, we assumed rest of the modules in pipeline are PGA. But we 1408d93f8e55SVinod Koul * are interested in last PGA (leaf PGA) in a pipeline to disconnect with 1409d93f8e55SVinod Koul * the sink when it is running (two FE to one BE or one FE to two BE) 1410d93f8e55SVinod Koul * scenarios 1411d93f8e55SVinod Koul */ 1412d93f8e55SVinod Koul static int skl_tplg_pga_event(struct snd_soc_dapm_widget *w, 1413d93f8e55SVinod Koul struct snd_kcontrol *k, int event) 1414d93f8e55SVinod Koul 1415d93f8e55SVinod Koul { 1416d93f8e55SVinod Koul struct snd_soc_dapm_context *dapm = w->dapm; 1417*bcc2a2dcSCezary Rojewski struct skl_dev *skl = get_skl_ctx(dapm->dev); 1418d93f8e55SVinod Koul 1419d93f8e55SVinod Koul switch (event) { 1420d93f8e55SVinod Koul case SND_SOC_DAPM_PRE_PMU: 1421d93f8e55SVinod Koul return skl_tplg_pga_dapm_pre_pmu_event(w, skl); 1422d93f8e55SVinod Koul 1423d93f8e55SVinod Koul case SND_SOC_DAPM_POST_PMD: 1424d93f8e55SVinod Koul return skl_tplg_pga_dapm_post_pmd_event(w, skl); 1425d93f8e55SVinod Koul } 1426d93f8e55SVinod Koul 1427d93f8e55SVinod Koul return 0; 1428d93f8e55SVinod Koul } 1429cfb0a873SVinod Koul 1430140adfbaSJeeja KP static int skl_tplg_tlv_control_get(struct snd_kcontrol *kcontrol, 1431140adfbaSJeeja KP unsigned int __user *data, unsigned int size) 1432140adfbaSJeeja KP { 1433140adfbaSJeeja KP struct soc_bytes_ext *sb = 1434140adfbaSJeeja KP (struct soc_bytes_ext *)kcontrol->private_value; 1435140adfbaSJeeja KP struct skl_algo_data *bc = (struct skl_algo_data *)sb->dobj.private; 14367d9f2911SOmair M Abdullah struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol); 14377d9f2911SOmair M Abdullah struct skl_module_cfg *mconfig = w->priv; 1438*bcc2a2dcSCezary Rojewski struct skl_dev *skl = get_skl_ctx(w->dapm->dev); 14397d9f2911SOmair M Abdullah 14407d9f2911SOmair M Abdullah if (w->power) 1441*bcc2a2dcSCezary Rojewski skl_get_module_params(skl, (u32 *)bc->params, 14420d682104SDharageswari R bc->size, bc->param_id, mconfig); 1443140adfbaSJeeja KP 144441556f68SVinod Koul /* decrement size for TLV header */ 144541556f68SVinod Koul size -= 2 * sizeof(u32); 144641556f68SVinod Koul 144741556f68SVinod Koul /* check size as we don't want to send kernel data */ 144841556f68SVinod Koul if (size > bc->max) 144941556f68SVinod Koul size = bc->max; 145041556f68SVinod Koul 1451140adfbaSJeeja KP if (bc->params) { 1452140adfbaSJeeja KP if (copy_to_user(data, &bc->param_id, sizeof(u32))) 1453140adfbaSJeeja KP return -EFAULT; 1454e8bc3c99SDan Carpenter if (copy_to_user(data + 1, &size, sizeof(u32))) 1455140adfbaSJeeja KP return -EFAULT; 1456e8bc3c99SDan Carpenter if (copy_to_user(data + 2, bc->params, size)) 1457140adfbaSJeeja KP return -EFAULT; 1458140adfbaSJeeja KP } 1459140adfbaSJeeja KP 1460140adfbaSJeeja KP return 0; 1461140adfbaSJeeja KP } 1462140adfbaSJeeja KP 1463140adfbaSJeeja KP #define SKL_PARAM_VENDOR_ID 0xff 1464140adfbaSJeeja KP 1465140adfbaSJeeja KP static int skl_tplg_tlv_control_set(struct snd_kcontrol *kcontrol, 1466140adfbaSJeeja KP const unsigned int __user *data, unsigned int size) 1467140adfbaSJeeja KP { 1468140adfbaSJeeja KP struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol); 1469140adfbaSJeeja KP struct skl_module_cfg *mconfig = w->priv; 1470140adfbaSJeeja KP struct soc_bytes_ext *sb = 1471140adfbaSJeeja KP (struct soc_bytes_ext *)kcontrol->private_value; 1472140adfbaSJeeja KP struct skl_algo_data *ac = (struct skl_algo_data *)sb->dobj.private; 1473*bcc2a2dcSCezary Rojewski struct skl_dev *skl = get_skl_ctx(w->dapm->dev); 1474140adfbaSJeeja KP 1475140adfbaSJeeja KP if (ac->params) { 1476a8cd7066SKamil Lulko /* 1477a8cd7066SKamil Lulko * Widget data is expected to be stripped of T and L 1478a8cd7066SKamil Lulko */ 1479a8cd7066SKamil Lulko size -= 2 * sizeof(unsigned int); 1480a8cd7066SKamil Lulko data += 2; 1481a8cd7066SKamil Lulko 14820d682104SDharageswari R if (size > ac->max) 14830d682104SDharageswari R return -EINVAL; 14840d682104SDharageswari R ac->size = size; 1485a8cd7066SKamil Lulko 1486140adfbaSJeeja KP if (copy_from_user(ac->params, data, size)) 1487140adfbaSJeeja KP return -EFAULT; 1488140adfbaSJeeja KP 1489140adfbaSJeeja KP if (w->power) 1490*bcc2a2dcSCezary Rojewski return skl_set_module_params(skl, 14910d682104SDharageswari R (u32 *)ac->params, ac->size, 1492140adfbaSJeeja KP ac->param_id, mconfig); 1493140adfbaSJeeja KP } 1494140adfbaSJeeja KP 1495140adfbaSJeeja KP return 0; 1496140adfbaSJeeja KP } 1497140adfbaSJeeja KP 14987a1b749bSDharageswari R static int skl_tplg_mic_control_get(struct snd_kcontrol *kcontrol, 14997a1b749bSDharageswari R struct snd_ctl_elem_value *ucontrol) 15007a1b749bSDharageswari R { 15017a1b749bSDharageswari R struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol); 15027a1b749bSDharageswari R struct skl_module_cfg *mconfig = w->priv; 15037a1b749bSDharageswari R struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; 15047a1b749bSDharageswari R u32 ch_type = *((u32 *)ec->dobj.private); 15057a1b749bSDharageswari R 15067a1b749bSDharageswari R if (mconfig->dmic_ch_type == ch_type) 15077a1b749bSDharageswari R ucontrol->value.enumerated.item[0] = 15087a1b749bSDharageswari R mconfig->dmic_ch_combo_index; 15097a1b749bSDharageswari R else 15107a1b749bSDharageswari R ucontrol->value.enumerated.item[0] = 0; 15117a1b749bSDharageswari R 15127a1b749bSDharageswari R return 0; 15137a1b749bSDharageswari R } 15147a1b749bSDharageswari R 15157a1b749bSDharageswari R static int skl_fill_mic_sel_params(struct skl_module_cfg *mconfig, 15167a1b749bSDharageswari R struct skl_mic_sel_config *mic_cfg, struct device *dev) 15177a1b749bSDharageswari R { 15187a1b749bSDharageswari R struct skl_specific_cfg *sp_cfg = &mconfig->formats_config; 15197a1b749bSDharageswari R 15207a1b749bSDharageswari R sp_cfg->caps_size = sizeof(struct skl_mic_sel_config); 15217a1b749bSDharageswari R sp_cfg->set_params = SKL_PARAM_SET; 15227a1b749bSDharageswari R sp_cfg->param_id = 0x00; 15237a1b749bSDharageswari R if (!sp_cfg->caps) { 15247a1b749bSDharageswari R sp_cfg->caps = devm_kzalloc(dev, sp_cfg->caps_size, GFP_KERNEL); 15257a1b749bSDharageswari R if (!sp_cfg->caps) 15267a1b749bSDharageswari R return -ENOMEM; 15277a1b749bSDharageswari R } 15287a1b749bSDharageswari R 15297a1b749bSDharageswari R mic_cfg->mic_switch = SKL_MIC_SEL_SWITCH; 15307a1b749bSDharageswari R mic_cfg->flags = 0; 15317a1b749bSDharageswari R memcpy(sp_cfg->caps, mic_cfg, sp_cfg->caps_size); 15327a1b749bSDharageswari R 15337a1b749bSDharageswari R return 0; 15347a1b749bSDharageswari R } 15357a1b749bSDharageswari R 15367a1b749bSDharageswari R static int skl_tplg_mic_control_set(struct snd_kcontrol *kcontrol, 15377a1b749bSDharageswari R struct snd_ctl_elem_value *ucontrol) 15387a1b749bSDharageswari R { 15397a1b749bSDharageswari R struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol); 15407a1b749bSDharageswari R struct skl_module_cfg *mconfig = w->priv; 15417a1b749bSDharageswari R struct skl_mic_sel_config mic_cfg = {0}; 15427a1b749bSDharageswari R struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; 15437a1b749bSDharageswari R u32 ch_type = *((u32 *)ec->dobj.private); 15447a1b749bSDharageswari R const int *list; 15457a1b749bSDharageswari R u8 in_ch, out_ch, index; 15467a1b749bSDharageswari R 15477a1b749bSDharageswari R mconfig->dmic_ch_type = ch_type; 15487a1b749bSDharageswari R mconfig->dmic_ch_combo_index = ucontrol->value.enumerated.item[0]; 15497a1b749bSDharageswari R 15507a1b749bSDharageswari R /* enum control index 0 is INVALID, so no channels to be set */ 15517a1b749bSDharageswari R if (mconfig->dmic_ch_combo_index == 0) 15527a1b749bSDharageswari R return 0; 15537a1b749bSDharageswari R 15547a1b749bSDharageswari R /* No valid channel selection map for index 0, so offset by 1 */ 15557a1b749bSDharageswari R index = mconfig->dmic_ch_combo_index - 1; 15567a1b749bSDharageswari R 15577a1b749bSDharageswari R switch (ch_type) { 15587a1b749bSDharageswari R case SKL_CH_MONO: 15597a1b749bSDharageswari R if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_mono_list)) 15607a1b749bSDharageswari R return -EINVAL; 15617a1b749bSDharageswari R 15627a1b749bSDharageswari R list = &mic_mono_list[index]; 15637a1b749bSDharageswari R break; 15647a1b749bSDharageswari R 15657a1b749bSDharageswari R case SKL_CH_STEREO: 15667a1b749bSDharageswari R if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_stereo_list)) 15677a1b749bSDharageswari R return -EINVAL; 15687a1b749bSDharageswari R 15697a1b749bSDharageswari R list = mic_stereo_list[index]; 15707a1b749bSDharageswari R break; 15717a1b749bSDharageswari R 15727a1b749bSDharageswari R case SKL_CH_TRIO: 15737a1b749bSDharageswari R if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_trio_list)) 15747a1b749bSDharageswari R return -EINVAL; 15757a1b749bSDharageswari R 15767a1b749bSDharageswari R list = mic_trio_list[index]; 15777a1b749bSDharageswari R break; 15787a1b749bSDharageswari R 15797a1b749bSDharageswari R case SKL_CH_QUATRO: 15807a1b749bSDharageswari R if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_quatro_list)) 15817a1b749bSDharageswari R return -EINVAL; 15827a1b749bSDharageswari R 15837a1b749bSDharageswari R list = mic_quatro_list[index]; 15847a1b749bSDharageswari R break; 15857a1b749bSDharageswari R 15867a1b749bSDharageswari R default: 15877a1b749bSDharageswari R dev_err(w->dapm->dev, 15887a1b749bSDharageswari R "Invalid channel %d for mic_select module\n", 15897a1b749bSDharageswari R ch_type); 15907a1b749bSDharageswari R return -EINVAL; 15917a1b749bSDharageswari R 15927a1b749bSDharageswari R } 15937a1b749bSDharageswari R 15947a1b749bSDharageswari R /* channel type enum map to number of chanels for that type */ 15957a1b749bSDharageswari R for (out_ch = 0; out_ch < ch_type; out_ch++) { 15967a1b749bSDharageswari R in_ch = list[out_ch]; 15977a1b749bSDharageswari R mic_cfg.blob[out_ch][in_ch] = SKL_DEFAULT_MIC_SEL_GAIN; 15987a1b749bSDharageswari R } 15997a1b749bSDharageswari R 16007a1b749bSDharageswari R return skl_fill_mic_sel_params(mconfig, &mic_cfg, w->dapm->dev); 16017a1b749bSDharageswari R } 16027a1b749bSDharageswari R 1603cfb0a873SVinod Koul /* 16048871dcb9SJeeja KP * Fill the dma id for host and link. In case of passthrough 16058871dcb9SJeeja KP * pipeline, this will both host and link in the same 16068871dcb9SJeeja KP * pipeline, so need to copy the link and host based on dev_type 16078871dcb9SJeeja KP */ 16088871dcb9SJeeja KP static void skl_tplg_fill_dma_id(struct skl_module_cfg *mcfg, 16098871dcb9SJeeja KP struct skl_pipe_params *params) 16108871dcb9SJeeja KP { 16118871dcb9SJeeja KP struct skl_pipe *pipe = mcfg->pipe; 16128871dcb9SJeeja KP 16138871dcb9SJeeja KP if (pipe->passthru) { 16148871dcb9SJeeja KP switch (mcfg->dev_type) { 16158871dcb9SJeeja KP case SKL_DEVICE_HDALINK: 16168871dcb9SJeeja KP pipe->p_params->link_dma_id = params->link_dma_id; 161712c3be0eSJeeja KP pipe->p_params->link_index = params->link_index; 16187f975a38SJeeja KP pipe->p_params->link_bps = params->link_bps; 16198871dcb9SJeeja KP break; 16208871dcb9SJeeja KP 16218871dcb9SJeeja KP case SKL_DEVICE_HDAHOST: 16228871dcb9SJeeja KP pipe->p_params->host_dma_id = params->host_dma_id; 16237f975a38SJeeja KP pipe->p_params->host_bps = params->host_bps; 16248871dcb9SJeeja KP break; 16258871dcb9SJeeja KP 16268871dcb9SJeeja KP default: 16278871dcb9SJeeja KP break; 16288871dcb9SJeeja KP } 16298871dcb9SJeeja KP pipe->p_params->s_fmt = params->s_fmt; 16308871dcb9SJeeja KP pipe->p_params->ch = params->ch; 16318871dcb9SJeeja KP pipe->p_params->s_freq = params->s_freq; 16328871dcb9SJeeja KP pipe->p_params->stream = params->stream; 163312c3be0eSJeeja KP pipe->p_params->format = params->format; 16348871dcb9SJeeja KP 16358871dcb9SJeeja KP } else { 16368871dcb9SJeeja KP memcpy(pipe->p_params, params, sizeof(*params)); 16378871dcb9SJeeja KP } 16388871dcb9SJeeja KP } 16398871dcb9SJeeja KP 16408871dcb9SJeeja KP /* 1641cfb0a873SVinod Koul * The FE params are passed by hw_params of the DAI. 1642cfb0a873SVinod Koul * On hw_params, the params are stored in Gateway module of the FE and we 1643cfb0a873SVinod Koul * need to calculate the format in DSP module configuration, that 1644cfb0a873SVinod Koul * conversion is done here 1645cfb0a873SVinod Koul */ 1646cfb0a873SVinod Koul int skl_tplg_update_pipe_params(struct device *dev, 1647cfb0a873SVinod Koul struct skl_module_cfg *mconfig, 1648cfb0a873SVinod Koul struct skl_pipe_params *params) 1649cfb0a873SVinod Koul { 1650f6fa56e2SRamesh Babu struct skl_module_res *res = &mconfig->module->resources[0]; 1651*bcc2a2dcSCezary Rojewski struct skl_dev *skl = get_skl_ctx(dev); 1652cfb0a873SVinod Koul struct skl_module_fmt *format = NULL; 1653f6fa56e2SRamesh Babu u8 cfg_idx = mconfig->pipe->cur_config_idx; 1654cfb0a873SVinod Koul 16558871dcb9SJeeja KP skl_tplg_fill_dma_id(mconfig, params); 1656f6fa56e2SRamesh Babu mconfig->fmt_idx = mconfig->mod_cfg[cfg_idx].fmt_idx; 1657f6fa56e2SRamesh Babu mconfig->res_idx = mconfig->mod_cfg[cfg_idx].res_idx; 1658f6fa56e2SRamesh Babu 1659f6fa56e2SRamesh Babu if (skl->nr_modules) 1660f6fa56e2SRamesh Babu return 0; 1661cfb0a873SVinod Koul 1662cfb0a873SVinod Koul if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) 1663f6fa56e2SRamesh Babu format = &mconfig->module->formats[0].inputs[0].fmt; 1664cfb0a873SVinod Koul else 1665f6fa56e2SRamesh Babu format = &mconfig->module->formats[0].outputs[0].fmt; 1666cfb0a873SVinod Koul 1667cfb0a873SVinod Koul /* set the hw_params */ 1668cfb0a873SVinod Koul format->s_freq = params->s_freq; 1669cfb0a873SVinod Koul format->channels = params->ch; 1670cfb0a873SVinod Koul format->valid_bit_depth = skl_get_bit_depth(params->s_fmt); 1671cfb0a873SVinod Koul 1672cfb0a873SVinod Koul /* 1673cfb0a873SVinod Koul * 16 bit is 16 bit container whereas 24 bit is in 32 bit 1674cfb0a873SVinod Koul * container so update bit depth accordingly 1675cfb0a873SVinod Koul */ 1676cfb0a873SVinod Koul switch (format->valid_bit_depth) { 1677cfb0a873SVinod Koul case SKL_DEPTH_16BIT: 1678cfb0a873SVinod Koul format->bit_depth = format->valid_bit_depth; 1679cfb0a873SVinod Koul break; 1680cfb0a873SVinod Koul 1681cfb0a873SVinod Koul case SKL_DEPTH_24BIT: 16826654f39eSJeeja KP case SKL_DEPTH_32BIT: 1683cfb0a873SVinod Koul format->bit_depth = SKL_DEPTH_32BIT; 1684cfb0a873SVinod Koul break; 1685cfb0a873SVinod Koul 1686cfb0a873SVinod Koul default: 1687cfb0a873SVinod Koul dev_err(dev, "Invalid bit depth %x for pipe\n", 1688cfb0a873SVinod Koul format->valid_bit_depth); 1689cfb0a873SVinod Koul return -EINVAL; 1690cfb0a873SVinod Koul } 1691cfb0a873SVinod Koul 1692cfb0a873SVinod Koul if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) { 1693f6fa56e2SRamesh Babu res->ibs = (format->s_freq / 1000) * 1694cfb0a873SVinod Koul (format->channels) * 1695cfb0a873SVinod Koul (format->bit_depth >> 3); 1696cfb0a873SVinod Koul } else { 1697f6fa56e2SRamesh Babu res->obs = (format->s_freq / 1000) * 1698cfb0a873SVinod Koul (format->channels) * 1699cfb0a873SVinod Koul (format->bit_depth >> 3); 1700cfb0a873SVinod Koul } 1701cfb0a873SVinod Koul 1702cfb0a873SVinod Koul return 0; 1703cfb0a873SVinod Koul } 1704cfb0a873SVinod Koul 1705cfb0a873SVinod Koul /* 1706cfb0a873SVinod Koul * Query the module config for the FE DAI 1707cfb0a873SVinod Koul * This is used to find the hw_params set for that DAI and apply to FE 1708cfb0a873SVinod Koul * pipeline 1709cfb0a873SVinod Koul */ 1710cfb0a873SVinod Koul struct skl_module_cfg * 1711cfb0a873SVinod Koul skl_tplg_fe_get_cpr_module(struct snd_soc_dai *dai, int stream) 1712cfb0a873SVinod Koul { 1713cfb0a873SVinod Koul struct snd_soc_dapm_widget *w; 1714cfb0a873SVinod Koul struct snd_soc_dapm_path *p = NULL; 1715cfb0a873SVinod Koul 1716cfb0a873SVinod Koul if (stream == SNDRV_PCM_STREAM_PLAYBACK) { 1717cfb0a873SVinod Koul w = dai->playback_widget; 1718f0900eb2SSubhransu S. Prusty snd_soc_dapm_widget_for_each_sink_path(w, p) { 1719cfb0a873SVinod Koul if (p->connect && p->sink->power && 1720cb1f904dSGuneshwor Singh !is_skl_dsp_widget_type(p->sink, dai->dev)) 1721cfb0a873SVinod Koul continue; 1722cfb0a873SVinod Koul 1723cfb0a873SVinod Koul if (p->sink->priv) { 1724cfb0a873SVinod Koul dev_dbg(dai->dev, "set params for %s\n", 1725cfb0a873SVinod Koul p->sink->name); 1726cfb0a873SVinod Koul return p->sink->priv; 1727cfb0a873SVinod Koul } 1728cfb0a873SVinod Koul } 1729cfb0a873SVinod Koul } else { 1730cfb0a873SVinod Koul w = dai->capture_widget; 1731f0900eb2SSubhransu S. Prusty snd_soc_dapm_widget_for_each_source_path(w, p) { 1732cfb0a873SVinod Koul if (p->connect && p->source->power && 1733cb1f904dSGuneshwor Singh !is_skl_dsp_widget_type(p->source, dai->dev)) 1734cfb0a873SVinod Koul continue; 1735cfb0a873SVinod Koul 1736cfb0a873SVinod Koul if (p->source->priv) { 1737cfb0a873SVinod Koul dev_dbg(dai->dev, "set params for %s\n", 1738cfb0a873SVinod Koul p->source->name); 1739cfb0a873SVinod Koul return p->source->priv; 1740cfb0a873SVinod Koul } 1741cfb0a873SVinod Koul } 1742cfb0a873SVinod Koul } 1743cfb0a873SVinod Koul 1744cfb0a873SVinod Koul return NULL; 1745cfb0a873SVinod Koul } 1746cfb0a873SVinod Koul 1747718a42b5SDharageswari.R static struct skl_module_cfg *skl_get_mconfig_pb_cpr( 1748718a42b5SDharageswari.R struct snd_soc_dai *dai, struct snd_soc_dapm_widget *w) 1749718a42b5SDharageswari.R { 1750718a42b5SDharageswari.R struct snd_soc_dapm_path *p; 1751718a42b5SDharageswari.R struct skl_module_cfg *mconfig = NULL; 1752718a42b5SDharageswari.R 1753718a42b5SDharageswari.R snd_soc_dapm_widget_for_each_source_path(w, p) { 1754718a42b5SDharageswari.R if (w->endpoints[SND_SOC_DAPM_DIR_OUT] > 0) { 1755718a42b5SDharageswari.R if (p->connect && 1756718a42b5SDharageswari.R (p->sink->id == snd_soc_dapm_aif_out) && 1757718a42b5SDharageswari.R p->source->priv) { 1758718a42b5SDharageswari.R mconfig = p->source->priv; 1759718a42b5SDharageswari.R return mconfig; 1760718a42b5SDharageswari.R } 1761718a42b5SDharageswari.R mconfig = skl_get_mconfig_pb_cpr(dai, p->source); 1762718a42b5SDharageswari.R if (mconfig) 1763718a42b5SDharageswari.R return mconfig; 1764718a42b5SDharageswari.R } 1765718a42b5SDharageswari.R } 1766718a42b5SDharageswari.R return mconfig; 1767718a42b5SDharageswari.R } 1768718a42b5SDharageswari.R 1769718a42b5SDharageswari.R static struct skl_module_cfg *skl_get_mconfig_cap_cpr( 1770718a42b5SDharageswari.R struct snd_soc_dai *dai, struct snd_soc_dapm_widget *w) 1771718a42b5SDharageswari.R { 1772718a42b5SDharageswari.R struct snd_soc_dapm_path *p; 1773718a42b5SDharageswari.R struct skl_module_cfg *mconfig = NULL; 1774718a42b5SDharageswari.R 1775718a42b5SDharageswari.R snd_soc_dapm_widget_for_each_sink_path(w, p) { 1776718a42b5SDharageswari.R if (w->endpoints[SND_SOC_DAPM_DIR_IN] > 0) { 1777718a42b5SDharageswari.R if (p->connect && 1778718a42b5SDharageswari.R (p->source->id == snd_soc_dapm_aif_in) && 1779718a42b5SDharageswari.R p->sink->priv) { 1780718a42b5SDharageswari.R mconfig = p->sink->priv; 1781718a42b5SDharageswari.R return mconfig; 1782718a42b5SDharageswari.R } 1783718a42b5SDharageswari.R mconfig = skl_get_mconfig_cap_cpr(dai, p->sink); 1784718a42b5SDharageswari.R if (mconfig) 1785718a42b5SDharageswari.R return mconfig; 1786718a42b5SDharageswari.R } 1787718a42b5SDharageswari.R } 1788718a42b5SDharageswari.R return mconfig; 1789718a42b5SDharageswari.R } 1790718a42b5SDharageswari.R 1791718a42b5SDharageswari.R struct skl_module_cfg * 1792718a42b5SDharageswari.R skl_tplg_be_get_cpr_module(struct snd_soc_dai *dai, int stream) 1793718a42b5SDharageswari.R { 1794718a42b5SDharageswari.R struct snd_soc_dapm_widget *w; 1795718a42b5SDharageswari.R struct skl_module_cfg *mconfig; 1796718a42b5SDharageswari.R 1797718a42b5SDharageswari.R if (stream == SNDRV_PCM_STREAM_PLAYBACK) { 1798718a42b5SDharageswari.R w = dai->playback_widget; 1799718a42b5SDharageswari.R mconfig = skl_get_mconfig_pb_cpr(dai, w); 1800718a42b5SDharageswari.R } else { 1801718a42b5SDharageswari.R w = dai->capture_widget; 1802718a42b5SDharageswari.R mconfig = skl_get_mconfig_cap_cpr(dai, w); 1803718a42b5SDharageswari.R } 1804718a42b5SDharageswari.R return mconfig; 1805718a42b5SDharageswari.R } 1806718a42b5SDharageswari.R 1807cfb0a873SVinod Koul static u8 skl_tplg_be_link_type(int dev_type) 1808cfb0a873SVinod Koul { 1809cfb0a873SVinod Koul int ret; 1810cfb0a873SVinod Koul 1811cfb0a873SVinod Koul switch (dev_type) { 1812cfb0a873SVinod Koul case SKL_DEVICE_BT: 1813cfb0a873SVinod Koul ret = NHLT_LINK_SSP; 1814cfb0a873SVinod Koul break; 1815cfb0a873SVinod Koul 1816cfb0a873SVinod Koul case SKL_DEVICE_DMIC: 1817cfb0a873SVinod Koul ret = NHLT_LINK_DMIC; 1818cfb0a873SVinod Koul break; 1819cfb0a873SVinod Koul 1820cfb0a873SVinod Koul case SKL_DEVICE_I2S: 1821cfb0a873SVinod Koul ret = NHLT_LINK_SSP; 1822cfb0a873SVinod Koul break; 1823cfb0a873SVinod Koul 1824cfb0a873SVinod Koul case SKL_DEVICE_HDALINK: 1825cfb0a873SVinod Koul ret = NHLT_LINK_HDA; 1826cfb0a873SVinod Koul break; 1827cfb0a873SVinod Koul 1828cfb0a873SVinod Koul default: 1829cfb0a873SVinod Koul ret = NHLT_LINK_INVALID; 1830cfb0a873SVinod Koul break; 1831cfb0a873SVinod Koul } 1832cfb0a873SVinod Koul 1833cfb0a873SVinod Koul return ret; 1834cfb0a873SVinod Koul } 1835cfb0a873SVinod Koul 1836cfb0a873SVinod Koul /* 1837cfb0a873SVinod Koul * Fill the BE gateway parameters 1838cfb0a873SVinod Koul * The BE gateway expects a blob of parameters which are kept in the ACPI 1839cfb0a873SVinod Koul * NHLT blob, so query the blob for interface type (i2s/pdm) and instance. 1840cfb0a873SVinod Koul * The port can have multiple settings so pick based on the PCM 1841cfb0a873SVinod Koul * parameters 1842cfb0a873SVinod Koul */ 1843cfb0a873SVinod Koul static int skl_tplg_be_fill_pipe_params(struct snd_soc_dai *dai, 1844cfb0a873SVinod Koul struct skl_module_cfg *mconfig, 1845cfb0a873SVinod Koul struct skl_pipe_params *params) 1846cfb0a873SVinod Koul { 1847cfb0a873SVinod Koul struct nhlt_specific_cfg *cfg; 1848*bcc2a2dcSCezary Rojewski struct skl_dev *skl = get_skl_ctx(dai->dev); 1849cfb0a873SVinod Koul int link_type = skl_tplg_be_link_type(mconfig->dev_type); 1850db2f586bSSenthilnathan Veppur u8 dev_type = skl_tplg_be_dev_type(mconfig->dev_type); 1851cfb0a873SVinod Koul 18528871dcb9SJeeja KP skl_tplg_fill_dma_id(mconfig, params); 1853cfb0a873SVinod Koul 1854b30c275eSJeeja KP if (link_type == NHLT_LINK_HDA) 1855b30c275eSJeeja KP return 0; 1856b30c275eSJeeja KP 1857cfb0a873SVinod Koul /* update the blob based on virtual bus_id*/ 1858cfb0a873SVinod Koul cfg = skl_get_ep_blob(skl, mconfig->vbus_id, link_type, 1859cfb0a873SVinod Koul params->s_fmt, params->ch, 1860db2f586bSSenthilnathan Veppur params->s_freq, params->stream, 1861db2f586bSSenthilnathan Veppur dev_type); 1862cfb0a873SVinod Koul if (cfg) { 1863cfb0a873SVinod Koul mconfig->formats_config.caps_size = cfg->size; 1864bc03281aSJeeja KP mconfig->formats_config.caps = (u32 *) &cfg->caps; 1865cfb0a873SVinod Koul } else { 1866cfb0a873SVinod Koul dev_err(dai->dev, "Blob NULL for id %x type %d dirn %d\n", 1867cfb0a873SVinod Koul mconfig->vbus_id, link_type, 1868cfb0a873SVinod Koul params->stream); 1869cfb0a873SVinod Koul dev_err(dai->dev, "PCM: ch %d, freq %d, fmt %d\n", 1870cfb0a873SVinod Koul params->ch, params->s_freq, params->s_fmt); 1871cfb0a873SVinod Koul return -EINVAL; 1872cfb0a873SVinod Koul } 1873cfb0a873SVinod Koul 1874cfb0a873SVinod Koul return 0; 1875cfb0a873SVinod Koul } 1876cfb0a873SVinod Koul 1877cfb0a873SVinod Koul static int skl_tplg_be_set_src_pipe_params(struct snd_soc_dai *dai, 1878cfb0a873SVinod Koul struct snd_soc_dapm_widget *w, 1879cfb0a873SVinod Koul struct skl_pipe_params *params) 1880cfb0a873SVinod Koul { 1881cfb0a873SVinod Koul struct snd_soc_dapm_path *p; 18824d8adccbSSubhransu S. Prusty int ret = -EIO; 1883cfb0a873SVinod Koul 1884f0900eb2SSubhransu S. Prusty snd_soc_dapm_widget_for_each_source_path(w, p) { 1885cb1f904dSGuneshwor Singh if (p->connect && is_skl_dsp_widget_type(p->source, dai->dev) && 1886cfb0a873SVinod Koul p->source->priv) { 1887cfb0a873SVinod Koul 18889a03cb49SJeeja KP ret = skl_tplg_be_fill_pipe_params(dai, 18899a03cb49SJeeja KP p->source->priv, params); 18904d8adccbSSubhransu S. Prusty if (ret < 0) 18914d8adccbSSubhransu S. Prusty return ret; 1892cfb0a873SVinod Koul } else { 18939a03cb49SJeeja KP ret = skl_tplg_be_set_src_pipe_params(dai, 18949a03cb49SJeeja KP p->source, params); 18954d8adccbSSubhransu S. Prusty if (ret < 0) 18964d8adccbSSubhransu S. Prusty return ret; 1897cfb0a873SVinod Koul } 1898cfb0a873SVinod Koul } 1899cfb0a873SVinod Koul 19004d8adccbSSubhransu S. Prusty return ret; 1901cfb0a873SVinod Koul } 1902cfb0a873SVinod Koul 1903cfb0a873SVinod Koul static int skl_tplg_be_set_sink_pipe_params(struct snd_soc_dai *dai, 1904cfb0a873SVinod Koul struct snd_soc_dapm_widget *w, struct skl_pipe_params *params) 1905cfb0a873SVinod Koul { 1906cfb0a873SVinod Koul struct snd_soc_dapm_path *p = NULL; 19074d8adccbSSubhransu S. Prusty int ret = -EIO; 1908cfb0a873SVinod Koul 1909f0900eb2SSubhransu S. Prusty snd_soc_dapm_widget_for_each_sink_path(w, p) { 1910cb1f904dSGuneshwor Singh if (p->connect && is_skl_dsp_widget_type(p->sink, dai->dev) && 1911cfb0a873SVinod Koul p->sink->priv) { 1912cfb0a873SVinod Koul 19139a03cb49SJeeja KP ret = skl_tplg_be_fill_pipe_params(dai, 19149a03cb49SJeeja KP p->sink->priv, params); 19154d8adccbSSubhransu S. Prusty if (ret < 0) 19164d8adccbSSubhransu S. Prusty return ret; 19174d8adccbSSubhransu S. Prusty } else { 19184d8adccbSSubhransu S. Prusty ret = skl_tplg_be_set_sink_pipe_params( 1919cfb0a873SVinod Koul dai, p->sink, params); 19204d8adccbSSubhransu S. Prusty if (ret < 0) 19214d8adccbSSubhransu S. Prusty return ret; 1922cfb0a873SVinod Koul } 1923cfb0a873SVinod Koul } 1924cfb0a873SVinod Koul 19254d8adccbSSubhransu S. Prusty return ret; 1926cfb0a873SVinod Koul } 1927cfb0a873SVinod Koul 1928cfb0a873SVinod Koul /* 1929cfb0a873SVinod Koul * BE hw_params can be a source parameters (capture) or sink parameters 1930cfb0a873SVinod Koul * (playback). Based on sink and source we need to either find the source 1931cfb0a873SVinod Koul * list or the sink list and set the pipeline parameters 1932cfb0a873SVinod Koul */ 1933cfb0a873SVinod Koul int skl_tplg_be_update_params(struct snd_soc_dai *dai, 1934cfb0a873SVinod Koul struct skl_pipe_params *params) 1935cfb0a873SVinod Koul { 1936cfb0a873SVinod Koul struct snd_soc_dapm_widget *w; 1937cfb0a873SVinod Koul 1938cfb0a873SVinod Koul if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) { 1939cfb0a873SVinod Koul w = dai->playback_widget; 1940cfb0a873SVinod Koul 1941cfb0a873SVinod Koul return skl_tplg_be_set_src_pipe_params(dai, w, params); 1942cfb0a873SVinod Koul 1943cfb0a873SVinod Koul } else { 1944cfb0a873SVinod Koul w = dai->capture_widget; 1945cfb0a873SVinod Koul 1946cfb0a873SVinod Koul return skl_tplg_be_set_sink_pipe_params(dai, w, params); 1947cfb0a873SVinod Koul } 1948cfb0a873SVinod Koul 1949cfb0a873SVinod Koul return 0; 1950cfb0a873SVinod Koul } 19513af36706SVinod Koul 19523af36706SVinod Koul static const struct snd_soc_tplg_widget_events skl_tplg_widget_ops[] = { 19533af36706SVinod Koul {SKL_MIXER_EVENT, skl_tplg_mixer_event}, 19549a1e3507SVinod Koul {SKL_VMIXER_EVENT, skl_tplg_mixer_event}, 19553af36706SVinod Koul {SKL_PGA_EVENT, skl_tplg_pga_event}, 19563af36706SVinod Koul }; 19573af36706SVinod Koul 1958140adfbaSJeeja KP static const struct snd_soc_tplg_bytes_ext_ops skl_tlv_ops[] = { 1959140adfbaSJeeja KP {SKL_CONTROL_TYPE_BYTE_TLV, skl_tplg_tlv_control_get, 1960140adfbaSJeeja KP skl_tplg_tlv_control_set}, 1961140adfbaSJeeja KP }; 1962140adfbaSJeeja KP 19637a1b749bSDharageswari R static const struct snd_soc_tplg_kcontrol_ops skl_tplg_kcontrol_ops[] = { 19647a1b749bSDharageswari R { 19657a1b749bSDharageswari R .id = SKL_CONTROL_TYPE_MIC_SELECT, 19667a1b749bSDharageswari R .get = skl_tplg_mic_control_get, 19677a1b749bSDharageswari R .put = skl_tplg_mic_control_set, 19687a1b749bSDharageswari R }, 19697a1b749bSDharageswari R }; 19707a1b749bSDharageswari R 1971f6fa56e2SRamesh Babu static int skl_tplg_fill_pipe_cfg(struct device *dev, 1972f6fa56e2SRamesh Babu struct skl_pipe *pipe, u32 tkn, 1973f6fa56e2SRamesh Babu u32 tkn_val, int conf_idx, int dir) 1974f6fa56e2SRamesh Babu { 1975f6fa56e2SRamesh Babu struct skl_pipe_fmt *fmt; 1976f6fa56e2SRamesh Babu struct skl_path_config *config; 1977f6fa56e2SRamesh Babu 1978f6fa56e2SRamesh Babu switch (dir) { 1979f6fa56e2SRamesh Babu case SKL_DIR_IN: 1980f6fa56e2SRamesh Babu fmt = &pipe->configs[conf_idx].in_fmt; 1981f6fa56e2SRamesh Babu break; 1982f6fa56e2SRamesh Babu 1983f6fa56e2SRamesh Babu case SKL_DIR_OUT: 1984f6fa56e2SRamesh Babu fmt = &pipe->configs[conf_idx].out_fmt; 1985f6fa56e2SRamesh Babu break; 1986f6fa56e2SRamesh Babu 1987f6fa56e2SRamesh Babu default: 1988f6fa56e2SRamesh Babu dev_err(dev, "Invalid direction: %d\n", dir); 1989f6fa56e2SRamesh Babu return -EINVAL; 1990f6fa56e2SRamesh Babu } 1991f6fa56e2SRamesh Babu 1992f6fa56e2SRamesh Babu config = &pipe->configs[conf_idx]; 1993f6fa56e2SRamesh Babu 1994f6fa56e2SRamesh Babu switch (tkn) { 1995f6fa56e2SRamesh Babu case SKL_TKN_U32_CFG_FREQ: 1996f6fa56e2SRamesh Babu fmt->freq = tkn_val; 1997f6fa56e2SRamesh Babu break; 1998f6fa56e2SRamesh Babu 1999f6fa56e2SRamesh Babu case SKL_TKN_U8_CFG_CHAN: 2000f6fa56e2SRamesh Babu fmt->channels = tkn_val; 2001f6fa56e2SRamesh Babu break; 2002f6fa56e2SRamesh Babu 2003f6fa56e2SRamesh Babu case SKL_TKN_U8_CFG_BPS: 2004f6fa56e2SRamesh Babu fmt->bps = tkn_val; 2005f6fa56e2SRamesh Babu break; 2006f6fa56e2SRamesh Babu 2007f6fa56e2SRamesh Babu case SKL_TKN_U32_PATH_MEM_PGS: 2008f6fa56e2SRamesh Babu config->mem_pages = tkn_val; 2009f6fa56e2SRamesh Babu break; 2010f6fa56e2SRamesh Babu 2011f6fa56e2SRamesh Babu default: 2012f6fa56e2SRamesh Babu dev_err(dev, "Invalid token config: %d\n", tkn); 2013f6fa56e2SRamesh Babu return -EINVAL; 2014f6fa56e2SRamesh Babu } 2015f6fa56e2SRamesh Babu 2016f6fa56e2SRamesh Babu return 0; 2017f6fa56e2SRamesh Babu } 2018f6fa56e2SRamesh Babu 20196277e832SShreyas NC static int skl_tplg_fill_pipe_tkn(struct device *dev, 20206277e832SShreyas NC struct skl_pipe *pipe, u32 tkn, 20216277e832SShreyas NC u32 tkn_val) 20223af36706SVinod Koul { 20233af36706SVinod Koul 20246277e832SShreyas NC switch (tkn) { 20256277e832SShreyas NC case SKL_TKN_U32_PIPE_CONN_TYPE: 20266277e832SShreyas NC pipe->conn_type = tkn_val; 20276277e832SShreyas NC break; 20286277e832SShreyas NC 20296277e832SShreyas NC case SKL_TKN_U32_PIPE_PRIORITY: 20306277e832SShreyas NC pipe->pipe_priority = tkn_val; 20316277e832SShreyas NC break; 20326277e832SShreyas NC 20336277e832SShreyas NC case SKL_TKN_U32_PIPE_MEM_PGS: 20346277e832SShreyas NC pipe->memory_pages = tkn_val; 20356277e832SShreyas NC break; 20366277e832SShreyas NC 20378a0cb236SVinod Koul case SKL_TKN_U32_PMODE: 20388a0cb236SVinod Koul pipe->lp_mode = tkn_val; 20398a0cb236SVinod Koul break; 20408a0cb236SVinod Koul 2041f6fa56e2SRamesh Babu case SKL_TKN_U32_PIPE_DIRECTION: 2042f6fa56e2SRamesh Babu pipe->direction = tkn_val; 2043f6fa56e2SRamesh Babu break; 2044f6fa56e2SRamesh Babu 2045f6fa56e2SRamesh Babu case SKL_TKN_U32_NUM_CONFIGS: 2046f6fa56e2SRamesh Babu pipe->nr_cfgs = tkn_val; 2047f6fa56e2SRamesh Babu break; 2048f6fa56e2SRamesh Babu 20496277e832SShreyas NC default: 20506277e832SShreyas NC dev_err(dev, "Token not handled %d\n", tkn); 20516277e832SShreyas NC return -EINVAL; 20523af36706SVinod Koul } 20536277e832SShreyas NC 20546277e832SShreyas NC return 0; 20553af36706SVinod Koul } 20563af36706SVinod Koul 20573af36706SVinod Koul /* 20586277e832SShreyas NC * Add pipeline by parsing the relevant tokens 20596277e832SShreyas NC * Return an existing pipe if the pipe already exists. 20603af36706SVinod Koul */ 20616277e832SShreyas NC static int skl_tplg_add_pipe(struct device *dev, 2062*bcc2a2dcSCezary Rojewski struct skl_module_cfg *mconfig, struct skl_dev *skl, 20636277e832SShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem) 20643af36706SVinod Koul { 20653af36706SVinod Koul struct skl_pipeline *ppl; 20663af36706SVinod Koul struct skl_pipe *pipe; 20673af36706SVinod Koul struct skl_pipe_params *params; 20683af36706SVinod Koul 20693af36706SVinod Koul list_for_each_entry(ppl, &skl->ppl_list, node) { 20706277e832SShreyas NC if (ppl->pipe->ppl_id == tkn_elem->value) { 20716277e832SShreyas NC mconfig->pipe = ppl->pipe; 2072081dc8abSGuneshwor Singh return -EEXIST; 20736277e832SShreyas NC } 20743af36706SVinod Koul } 20753af36706SVinod Koul 20763af36706SVinod Koul ppl = devm_kzalloc(dev, sizeof(*ppl), GFP_KERNEL); 20773af36706SVinod Koul if (!ppl) 20786277e832SShreyas NC return -ENOMEM; 20793af36706SVinod Koul 20803af36706SVinod Koul pipe = devm_kzalloc(dev, sizeof(*pipe), GFP_KERNEL); 20813af36706SVinod Koul if (!pipe) 20826277e832SShreyas NC return -ENOMEM; 20833af36706SVinod Koul 20843af36706SVinod Koul params = devm_kzalloc(dev, sizeof(*params), GFP_KERNEL); 20853af36706SVinod Koul if (!params) 20866277e832SShreyas NC return -ENOMEM; 20873af36706SVinod Koul 20883af36706SVinod Koul pipe->p_params = params; 20896277e832SShreyas NC pipe->ppl_id = tkn_elem->value; 20903af36706SVinod Koul INIT_LIST_HEAD(&pipe->w_list); 20913af36706SVinod Koul 20923af36706SVinod Koul ppl->pipe = pipe; 20933af36706SVinod Koul list_add(&ppl->node, &skl->ppl_list); 20943af36706SVinod Koul 20956277e832SShreyas NC mconfig->pipe = pipe; 20966277e832SShreyas NC mconfig->pipe->state = SKL_PIPE_INVALID; 20976277e832SShreyas NC 20986277e832SShreyas NC return 0; 20993af36706SVinod Koul } 21003af36706SVinod Koul 21019e0784d0SAndy Shevchenko static int skl_tplg_get_uuid(struct device *dev, guid_t *guid, 210222ebd666SSriram Periyasamy struct snd_soc_tplg_vendor_uuid_elem *uuid_tkn) 21036277e832SShreyas NC { 210422ebd666SSriram Periyasamy if (uuid_tkn->token == SKL_TKN_UUID) { 21059e0784d0SAndy Shevchenko guid_copy(guid, (guid_t *)&uuid_tkn->uuid); 210622ebd666SSriram Periyasamy return 0; 210722ebd666SSriram Periyasamy } 210822ebd666SSriram Periyasamy 210922ebd666SSriram Periyasamy dev_err(dev, "Not an UUID token %d\n", uuid_tkn->token); 211022ebd666SSriram Periyasamy 211122ebd666SSriram Periyasamy return -EINVAL; 211222ebd666SSriram Periyasamy } 211322ebd666SSriram Periyasamy 211422ebd666SSriram Periyasamy static int skl_tplg_fill_pin(struct device *dev, 211522ebd666SSriram Periyasamy struct snd_soc_tplg_vendor_value_elem *tkn_elem, 211622ebd666SSriram Periyasamy struct skl_module_pin *m_pin, 211722ebd666SSriram Periyasamy int pin_index) 211822ebd666SSriram Periyasamy { 2119d9561474SSriram Periyasamy int ret; 2120d9561474SSriram Periyasamy 212122ebd666SSriram Periyasamy switch (tkn_elem->token) { 21226277e832SShreyas NC case SKL_TKN_U32_PIN_MOD_ID: 212322ebd666SSriram Periyasamy m_pin[pin_index].id.module_id = tkn_elem->value; 21246277e832SShreyas NC break; 21256277e832SShreyas NC 21266277e832SShreyas NC case SKL_TKN_U32_PIN_INST_ID: 212722ebd666SSriram Periyasamy m_pin[pin_index].id.instance_id = tkn_elem->value; 21286277e832SShreyas NC break; 21296277e832SShreyas NC 2130d9561474SSriram Periyasamy case SKL_TKN_UUID: 21319e0784d0SAndy Shevchenko ret = skl_tplg_get_uuid(dev, &m_pin[pin_index].id.mod_uuid, 2132d9561474SSriram Periyasamy (struct snd_soc_tplg_vendor_uuid_elem *)tkn_elem); 2133d9561474SSriram Periyasamy if (ret < 0) 2134d9561474SSriram Periyasamy return ret; 2135d9561474SSriram Periyasamy 21366277e832SShreyas NC break; 21376277e832SShreyas NC 21386277e832SShreyas NC default: 213922ebd666SSriram Periyasamy dev_err(dev, "%d Not a pin token\n", tkn_elem->token); 21406277e832SShreyas NC return -EINVAL; 21416277e832SShreyas NC } 21426277e832SShreyas NC 21436277e832SShreyas NC return 0; 21446277e832SShreyas NC } 21456277e832SShreyas NC 21466277e832SShreyas NC /* 21476277e832SShreyas NC * Parse for pin config specific tokens to fill up the 21486277e832SShreyas NC * module private data 21496277e832SShreyas NC */ 21506277e832SShreyas NC static int skl_tplg_fill_pins_info(struct device *dev, 21516277e832SShreyas NC struct skl_module_cfg *mconfig, 21526277e832SShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem, 21536277e832SShreyas NC int dir, int pin_count) 21546277e832SShreyas NC { 21556277e832SShreyas NC int ret; 21566277e832SShreyas NC struct skl_module_pin *m_pin; 21576277e832SShreyas NC 21586277e832SShreyas NC switch (dir) { 21596277e832SShreyas NC case SKL_DIR_IN: 21606277e832SShreyas NC m_pin = mconfig->m_in_pin; 21616277e832SShreyas NC break; 21626277e832SShreyas NC 21636277e832SShreyas NC case SKL_DIR_OUT: 21646277e832SShreyas NC m_pin = mconfig->m_out_pin; 21656277e832SShreyas NC break; 21666277e832SShreyas NC 21676277e832SShreyas NC default: 2168ecd286a9SColin Ian King dev_err(dev, "Invalid direction value\n"); 21696277e832SShreyas NC return -EINVAL; 21706277e832SShreyas NC } 21716277e832SShreyas NC 217222ebd666SSriram Periyasamy ret = skl_tplg_fill_pin(dev, tkn_elem, m_pin, pin_count); 21736277e832SShreyas NC if (ret < 0) 21746277e832SShreyas NC return ret; 21756277e832SShreyas NC 21766277e832SShreyas NC m_pin[pin_count].in_use = false; 21776277e832SShreyas NC m_pin[pin_count].pin_state = SKL_PIN_UNBIND; 21786277e832SShreyas NC 21796277e832SShreyas NC return 0; 21806277e832SShreyas NC } 21816277e832SShreyas NC 21826277e832SShreyas NC /* 21836277e832SShreyas NC * Fill up input/output module config format based 21846277e832SShreyas NC * on the direction 21856277e832SShreyas NC */ 21866277e832SShreyas NC static int skl_tplg_fill_fmt(struct device *dev, 2187ca312fdaSShreyas NC struct skl_module_fmt *dst_fmt, 2188ca312fdaSShreyas NC u32 tkn, u32 value) 21896277e832SShreyas NC { 21906277e832SShreyas NC switch (tkn) { 21916277e832SShreyas NC case SKL_TKN_U32_FMT_CH: 21926277e832SShreyas NC dst_fmt->channels = value; 21936277e832SShreyas NC break; 21946277e832SShreyas NC 21956277e832SShreyas NC case SKL_TKN_U32_FMT_FREQ: 21966277e832SShreyas NC dst_fmt->s_freq = value; 21976277e832SShreyas NC break; 21986277e832SShreyas NC 21996277e832SShreyas NC case SKL_TKN_U32_FMT_BIT_DEPTH: 22006277e832SShreyas NC dst_fmt->bit_depth = value; 22016277e832SShreyas NC break; 22026277e832SShreyas NC 22036277e832SShreyas NC case SKL_TKN_U32_FMT_SAMPLE_SIZE: 22046277e832SShreyas NC dst_fmt->valid_bit_depth = value; 22056277e832SShreyas NC break; 22066277e832SShreyas NC 22076277e832SShreyas NC case SKL_TKN_U32_FMT_CH_CONFIG: 22086277e832SShreyas NC dst_fmt->ch_cfg = value; 22096277e832SShreyas NC break; 22106277e832SShreyas NC 22116277e832SShreyas NC case SKL_TKN_U32_FMT_INTERLEAVE: 22126277e832SShreyas NC dst_fmt->interleaving_style = value; 22136277e832SShreyas NC break; 22146277e832SShreyas NC 22156277e832SShreyas NC case SKL_TKN_U32_FMT_SAMPLE_TYPE: 22166277e832SShreyas NC dst_fmt->sample_type = value; 22176277e832SShreyas NC break; 22186277e832SShreyas NC 22196277e832SShreyas NC case SKL_TKN_U32_FMT_CH_MAP: 22206277e832SShreyas NC dst_fmt->ch_map = value; 22216277e832SShreyas NC break; 22226277e832SShreyas NC 22236277e832SShreyas NC default: 2224ecd286a9SColin Ian King dev_err(dev, "Invalid token %d\n", tkn); 22256277e832SShreyas NC return -EINVAL; 22266277e832SShreyas NC } 22276277e832SShreyas NC 22286277e832SShreyas NC return 0; 22296277e832SShreyas NC } 22306277e832SShreyas NC 2231ca312fdaSShreyas NC static int skl_tplg_widget_fill_fmt(struct device *dev, 2232f6fa56e2SRamesh Babu struct skl_module_iface *fmt, 2233ca312fdaSShreyas NC u32 tkn, u32 val, u32 dir, int fmt_idx) 2234ca312fdaSShreyas NC { 2235ca312fdaSShreyas NC struct skl_module_fmt *dst_fmt; 2236ca312fdaSShreyas NC 2237f6fa56e2SRamesh Babu if (!fmt) 2238f6fa56e2SRamesh Babu return -EINVAL; 2239f6fa56e2SRamesh Babu 2240ca312fdaSShreyas NC switch (dir) { 2241ca312fdaSShreyas NC case SKL_DIR_IN: 2242f6fa56e2SRamesh Babu dst_fmt = &fmt->inputs[fmt_idx].fmt; 2243ca312fdaSShreyas NC break; 2244ca312fdaSShreyas NC 2245ca312fdaSShreyas NC case SKL_DIR_OUT: 2246f6fa56e2SRamesh Babu dst_fmt = &fmt->outputs[fmt_idx].fmt; 2247ca312fdaSShreyas NC break; 2248ca312fdaSShreyas NC 2249ca312fdaSShreyas NC default: 2250ca312fdaSShreyas NC dev_err(dev, "Invalid direction: %d\n", dir); 2251ca312fdaSShreyas NC return -EINVAL; 2252ca312fdaSShreyas NC } 2253ca312fdaSShreyas NC 2254ca312fdaSShreyas NC return skl_tplg_fill_fmt(dev, dst_fmt, tkn, val); 2255ca312fdaSShreyas NC } 2256ca312fdaSShreyas NC 22576277e832SShreyas NC static void skl_tplg_fill_pin_dynamic_val( 22586277e832SShreyas NC struct skl_module_pin *mpin, u32 pin_count, u32 value) 22594cd9899fSHardik T Shah { 22604cd9899fSHardik T Shah int i; 22614cd9899fSHardik T Shah 22626277e832SShreyas NC for (i = 0; i < pin_count; i++) 22636277e832SShreyas NC mpin[i].is_dynamic = value; 22644cd9899fSHardik T Shah } 22656277e832SShreyas NC 22666277e832SShreyas NC /* 2267db6ed55dSShreyas NC * Resource table in the manifest has pin specific resources 2268db6ed55dSShreyas NC * like pin and pin buffer size 2269db6ed55dSShreyas NC */ 2270db6ed55dSShreyas NC static int skl_tplg_manifest_pin_res_tkn(struct device *dev, 2271db6ed55dSShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem, 2272db6ed55dSShreyas NC struct skl_module_res *res, int pin_idx, int dir) 2273db6ed55dSShreyas NC { 2274db6ed55dSShreyas NC struct skl_module_pin_resources *m_pin; 2275db6ed55dSShreyas NC 2276db6ed55dSShreyas NC switch (dir) { 2277db6ed55dSShreyas NC case SKL_DIR_IN: 2278db6ed55dSShreyas NC m_pin = &res->input[pin_idx]; 2279db6ed55dSShreyas NC break; 2280db6ed55dSShreyas NC 2281db6ed55dSShreyas NC case SKL_DIR_OUT: 2282db6ed55dSShreyas NC m_pin = &res->output[pin_idx]; 2283db6ed55dSShreyas NC break; 2284db6ed55dSShreyas NC 2285db6ed55dSShreyas NC default: 2286db6ed55dSShreyas NC dev_err(dev, "Invalid pin direction: %d\n", dir); 2287db6ed55dSShreyas NC return -EINVAL; 2288db6ed55dSShreyas NC } 2289db6ed55dSShreyas NC 2290db6ed55dSShreyas NC switch (tkn_elem->token) { 2291db6ed55dSShreyas NC case SKL_TKN_MM_U32_RES_PIN_ID: 2292db6ed55dSShreyas NC m_pin->pin_index = tkn_elem->value; 2293db6ed55dSShreyas NC break; 2294db6ed55dSShreyas NC 2295db6ed55dSShreyas NC case SKL_TKN_MM_U32_PIN_BUF: 2296db6ed55dSShreyas NC m_pin->buf_size = tkn_elem->value; 2297db6ed55dSShreyas NC break; 2298db6ed55dSShreyas NC 2299db6ed55dSShreyas NC default: 2300db6ed55dSShreyas NC dev_err(dev, "Invalid token: %d\n", tkn_elem->token); 2301db6ed55dSShreyas NC return -EINVAL; 2302db6ed55dSShreyas NC } 2303db6ed55dSShreyas NC 2304db6ed55dSShreyas NC return 0; 2305db6ed55dSShreyas NC } 2306db6ed55dSShreyas NC 2307db6ed55dSShreyas NC /* 2308db6ed55dSShreyas NC * Fill module specific resources from the manifest's resource 2309db6ed55dSShreyas NC * table like CPS, DMA size, mem_pages. 2310db6ed55dSShreyas NC */ 2311db6ed55dSShreyas NC static int skl_tplg_fill_res_tkn(struct device *dev, 2312db6ed55dSShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem, 2313db6ed55dSShreyas NC struct skl_module_res *res, 2314db6ed55dSShreyas NC int pin_idx, int dir) 2315db6ed55dSShreyas NC { 2316db6ed55dSShreyas NC int ret, tkn_count = 0; 2317db6ed55dSShreyas NC 2318db6ed55dSShreyas NC if (!res) 2319db6ed55dSShreyas NC return -EINVAL; 2320db6ed55dSShreyas NC 2321db6ed55dSShreyas NC switch (tkn_elem->token) { 2322db6ed55dSShreyas NC case SKL_TKN_MM_U32_CPS: 2323db6ed55dSShreyas NC res->cps = tkn_elem->value; 2324db6ed55dSShreyas NC break; 2325db6ed55dSShreyas NC 2326db6ed55dSShreyas NC case SKL_TKN_MM_U32_DMA_SIZE: 2327db6ed55dSShreyas NC res->dma_buffer_size = tkn_elem->value; 2328db6ed55dSShreyas NC break; 2329db6ed55dSShreyas NC 2330db6ed55dSShreyas NC case SKL_TKN_MM_U32_CPC: 2331db6ed55dSShreyas NC res->cpc = tkn_elem->value; 2332db6ed55dSShreyas NC break; 2333db6ed55dSShreyas NC 2334db6ed55dSShreyas NC case SKL_TKN_U32_MEM_PAGES: 2335db6ed55dSShreyas NC res->is_pages = tkn_elem->value; 2336db6ed55dSShreyas NC break; 2337db6ed55dSShreyas NC 2338db6ed55dSShreyas NC case SKL_TKN_U32_OBS: 2339db6ed55dSShreyas NC res->obs = tkn_elem->value; 2340db6ed55dSShreyas NC break; 2341db6ed55dSShreyas NC 2342db6ed55dSShreyas NC case SKL_TKN_U32_IBS: 2343db6ed55dSShreyas NC res->ibs = tkn_elem->value; 2344db6ed55dSShreyas NC break; 2345db6ed55dSShreyas NC 2346f6fa56e2SRamesh Babu case SKL_TKN_U32_MAX_MCPS: 2347f6fa56e2SRamesh Babu res->cps = tkn_elem->value; 2348f6fa56e2SRamesh Babu break; 2349f6fa56e2SRamesh Babu 2350db6ed55dSShreyas NC case SKL_TKN_MM_U32_RES_PIN_ID: 2351db6ed55dSShreyas NC case SKL_TKN_MM_U32_PIN_BUF: 2352db6ed55dSShreyas NC ret = skl_tplg_manifest_pin_res_tkn(dev, tkn_elem, res, 2353db6ed55dSShreyas NC pin_idx, dir); 2354db6ed55dSShreyas NC if (ret < 0) 2355db6ed55dSShreyas NC return ret; 2356db6ed55dSShreyas NC break; 2357db6ed55dSShreyas NC 2358db6ed55dSShreyas NC default: 2359db6ed55dSShreyas NC dev_err(dev, "Not a res type token: %d", tkn_elem->token); 2360db6ed55dSShreyas NC return -EINVAL; 2361db6ed55dSShreyas NC 2362db6ed55dSShreyas NC } 2363db6ed55dSShreyas NC tkn_count++; 2364db6ed55dSShreyas NC 2365db6ed55dSShreyas NC return tkn_count; 2366db6ed55dSShreyas NC } 2367db6ed55dSShreyas NC 2368db6ed55dSShreyas NC /* 23696277e832SShreyas NC * Parse tokens to fill up the module private data 23706277e832SShreyas NC */ 23716277e832SShreyas NC static int skl_tplg_get_token(struct device *dev, 23726277e832SShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem, 2373*bcc2a2dcSCezary Rojewski struct skl_dev *skl, struct skl_module_cfg *mconfig) 23746277e832SShreyas NC { 23756277e832SShreyas NC int tkn_count = 0; 23766277e832SShreyas NC int ret; 23776277e832SShreyas NC static int is_pipe_exists; 2378f6fa56e2SRamesh Babu static int pin_index, dir, conf_idx; 2379f6fa56e2SRamesh Babu struct skl_module_iface *iface = NULL; 2380f6fa56e2SRamesh Babu struct skl_module_res *res = NULL; 2381f6fa56e2SRamesh Babu int res_idx = mconfig->res_idx; 2382f6fa56e2SRamesh Babu int fmt_idx = mconfig->fmt_idx; 2383f6fa56e2SRamesh Babu 2384f6fa56e2SRamesh Babu /* 2385f6fa56e2SRamesh Babu * If the manifest structure contains no modules, fill all 2386f6fa56e2SRamesh Babu * the module data to 0th index. 2387f6fa56e2SRamesh Babu * res_idx and fmt_idx are default set to 0. 2388f6fa56e2SRamesh Babu */ 2389f6fa56e2SRamesh Babu if (skl->nr_modules == 0) { 2390f6fa56e2SRamesh Babu res = &mconfig->module->resources[res_idx]; 2391f6fa56e2SRamesh Babu iface = &mconfig->module->formats[fmt_idx]; 2392f6fa56e2SRamesh Babu } 23936277e832SShreyas NC 23946277e832SShreyas NC if (tkn_elem->token > SKL_TKN_MAX) 23956277e832SShreyas NC return -EINVAL; 23966277e832SShreyas NC 23976277e832SShreyas NC switch (tkn_elem->token) { 23986277e832SShreyas NC case SKL_TKN_U8_IN_QUEUE_COUNT: 2399f6fa56e2SRamesh Babu mconfig->module->max_input_pins = tkn_elem->value; 24006277e832SShreyas NC break; 24016277e832SShreyas NC 24026277e832SShreyas NC case SKL_TKN_U8_OUT_QUEUE_COUNT: 2403f6fa56e2SRamesh Babu mconfig->module->max_output_pins = tkn_elem->value; 24046277e832SShreyas NC break; 24056277e832SShreyas NC 24066277e832SShreyas NC case SKL_TKN_U8_DYN_IN_PIN: 24076277e832SShreyas NC if (!mconfig->m_in_pin) 2408a86854d0SKees Cook mconfig->m_in_pin = 2409a86854d0SKees Cook devm_kcalloc(dev, MAX_IN_QUEUE, 2410a86854d0SKees Cook sizeof(*mconfig->m_in_pin), 2411a86854d0SKees Cook GFP_KERNEL); 2412f6fa56e2SRamesh Babu if (!mconfig->m_in_pin) 24136277e832SShreyas NC return -ENOMEM; 24146277e832SShreyas NC 2415f6fa56e2SRamesh Babu skl_tplg_fill_pin_dynamic_val(mconfig->m_in_pin, MAX_IN_QUEUE, 2416f6fa56e2SRamesh Babu tkn_elem->value); 24176277e832SShreyas NC break; 24186277e832SShreyas NC 24196277e832SShreyas NC case SKL_TKN_U8_DYN_OUT_PIN: 24206277e832SShreyas NC if (!mconfig->m_out_pin) 2421a86854d0SKees Cook mconfig->m_out_pin = 2422a86854d0SKees Cook devm_kcalloc(dev, MAX_IN_QUEUE, 2423a86854d0SKees Cook sizeof(*mconfig->m_in_pin), 2424a86854d0SKees Cook GFP_KERNEL); 2425f6fa56e2SRamesh Babu if (!mconfig->m_out_pin) 24266277e832SShreyas NC return -ENOMEM; 24276277e832SShreyas NC 2428f6fa56e2SRamesh Babu skl_tplg_fill_pin_dynamic_val(mconfig->m_out_pin, MAX_OUT_QUEUE, 2429f6fa56e2SRamesh Babu tkn_elem->value); 24306277e832SShreyas NC break; 24316277e832SShreyas NC 24326277e832SShreyas NC case SKL_TKN_U8_TIME_SLOT: 24336277e832SShreyas NC mconfig->time_slot = tkn_elem->value; 24346277e832SShreyas NC break; 24356277e832SShreyas NC 24366277e832SShreyas NC case SKL_TKN_U8_CORE_ID: 24376277e832SShreyas NC mconfig->core_id = tkn_elem->value; 24389c80c5a8STakashi Iwai break; 24396277e832SShreyas NC 24406277e832SShreyas NC case SKL_TKN_U8_MOD_TYPE: 24416277e832SShreyas NC mconfig->m_type = tkn_elem->value; 24426277e832SShreyas NC break; 24436277e832SShreyas NC 24446277e832SShreyas NC case SKL_TKN_U8_DEV_TYPE: 24456277e832SShreyas NC mconfig->dev_type = tkn_elem->value; 24466277e832SShreyas NC break; 24476277e832SShreyas NC 24486277e832SShreyas NC case SKL_TKN_U8_HW_CONN_TYPE: 24496277e832SShreyas NC mconfig->hw_conn_type = tkn_elem->value; 24506277e832SShreyas NC break; 24516277e832SShreyas NC 24526277e832SShreyas NC case SKL_TKN_U16_MOD_INST_ID: 24536277e832SShreyas NC mconfig->id.instance_id = 24546277e832SShreyas NC tkn_elem->value; 24556277e832SShreyas NC break; 24566277e832SShreyas NC 24576277e832SShreyas NC case SKL_TKN_U32_MEM_PAGES: 24586277e832SShreyas NC case SKL_TKN_U32_MAX_MCPS: 24596277e832SShreyas NC case SKL_TKN_U32_OBS: 24606277e832SShreyas NC case SKL_TKN_U32_IBS: 24612b79b15cSColin Ian King ret = skl_tplg_fill_res_tkn(dev, tkn_elem, res, pin_index, dir); 2462f6fa56e2SRamesh Babu if (ret < 0) 2463f6fa56e2SRamesh Babu return ret; 2464f6fa56e2SRamesh Babu 24656277e832SShreyas NC break; 24666277e832SShreyas NC 24676277e832SShreyas NC case SKL_TKN_U32_VBUS_ID: 24686277e832SShreyas NC mconfig->vbus_id = tkn_elem->value; 24696277e832SShreyas NC break; 24706277e832SShreyas NC 24716277e832SShreyas NC case SKL_TKN_U32_PARAMS_FIXUP: 24726277e832SShreyas NC mconfig->params_fixup = tkn_elem->value; 24736277e832SShreyas NC break; 24746277e832SShreyas NC 24756277e832SShreyas NC case SKL_TKN_U32_CONVERTER: 24766277e832SShreyas NC mconfig->converter = tkn_elem->value; 24776277e832SShreyas NC break; 24786277e832SShreyas NC 2479c0116be3SSubhransu S. Prusty case SKL_TKN_U32_D0I3_CAPS: 24806bd9dcf3SVinod Koul mconfig->d0i3_caps = tkn_elem->value; 24816bd9dcf3SVinod Koul break; 24826bd9dcf3SVinod Koul 24836277e832SShreyas NC case SKL_TKN_U32_PIPE_ID: 24846277e832SShreyas NC ret = skl_tplg_add_pipe(dev, 24856277e832SShreyas NC mconfig, skl, tkn_elem); 24866277e832SShreyas NC 2487081dc8abSGuneshwor Singh if (ret < 0) { 2488081dc8abSGuneshwor Singh if (ret == -EEXIST) { 24896277e832SShreyas NC is_pipe_exists = 1; 2490081dc8abSGuneshwor Singh break; 2491081dc8abSGuneshwor Singh } 2492081dc8abSGuneshwor Singh return is_pipe_exists; 2493081dc8abSGuneshwor Singh } 24946277e832SShreyas NC 24956277e832SShreyas NC break; 24966277e832SShreyas NC 2497f6fa56e2SRamesh Babu case SKL_TKN_U32_PIPE_CONFIG_ID: 2498f6fa56e2SRamesh Babu conf_idx = tkn_elem->value; 2499f6fa56e2SRamesh Babu break; 2500f6fa56e2SRamesh Babu 25016277e832SShreyas NC case SKL_TKN_U32_PIPE_CONN_TYPE: 25026277e832SShreyas NC case SKL_TKN_U32_PIPE_PRIORITY: 25036277e832SShreyas NC case SKL_TKN_U32_PIPE_MEM_PGS: 25048a0cb236SVinod Koul case SKL_TKN_U32_PMODE: 2505f6fa56e2SRamesh Babu case SKL_TKN_U32_PIPE_DIRECTION: 2506f6fa56e2SRamesh Babu case SKL_TKN_U32_NUM_CONFIGS: 25076277e832SShreyas NC if (is_pipe_exists) { 25086277e832SShreyas NC ret = skl_tplg_fill_pipe_tkn(dev, mconfig->pipe, 25096277e832SShreyas NC tkn_elem->token, tkn_elem->value); 25106277e832SShreyas NC if (ret < 0) 25116277e832SShreyas NC return ret; 25126277e832SShreyas NC } 25136277e832SShreyas NC 25146277e832SShreyas NC break; 25156277e832SShreyas NC 2516f6fa56e2SRamesh Babu case SKL_TKN_U32_PATH_MEM_PGS: 2517f6fa56e2SRamesh Babu case SKL_TKN_U32_CFG_FREQ: 2518f6fa56e2SRamesh Babu case SKL_TKN_U8_CFG_CHAN: 2519f6fa56e2SRamesh Babu case SKL_TKN_U8_CFG_BPS: 2520f6fa56e2SRamesh Babu if (mconfig->pipe->nr_cfgs) { 2521f6fa56e2SRamesh Babu ret = skl_tplg_fill_pipe_cfg(dev, mconfig->pipe, 2522f6fa56e2SRamesh Babu tkn_elem->token, tkn_elem->value, 2523f6fa56e2SRamesh Babu conf_idx, dir); 2524f6fa56e2SRamesh Babu if (ret < 0) 2525f6fa56e2SRamesh Babu return ret; 2526f6fa56e2SRamesh Babu } 2527f6fa56e2SRamesh Babu break; 2528f6fa56e2SRamesh Babu 2529f6fa56e2SRamesh Babu case SKL_TKN_CFG_MOD_RES_ID: 2530f6fa56e2SRamesh Babu mconfig->mod_cfg[conf_idx].res_idx = tkn_elem->value; 2531f6fa56e2SRamesh Babu break; 2532f6fa56e2SRamesh Babu 2533f6fa56e2SRamesh Babu case SKL_TKN_CFG_MOD_FMT_ID: 2534f6fa56e2SRamesh Babu mconfig->mod_cfg[conf_idx].fmt_idx = tkn_elem->value; 2535f6fa56e2SRamesh Babu break; 2536f6fa56e2SRamesh Babu 25376277e832SShreyas NC /* 25386277e832SShreyas NC * SKL_TKN_U32_DIR_PIN_COUNT token has the value for both 25396277e832SShreyas NC * direction and the pin count. The first four bits represent 25406277e832SShreyas NC * direction and next four the pin count. 25416277e832SShreyas NC */ 25426277e832SShreyas NC case SKL_TKN_U32_DIR_PIN_COUNT: 25436277e832SShreyas NC dir = tkn_elem->value & SKL_IN_DIR_BIT_MASK; 25446277e832SShreyas NC pin_index = (tkn_elem->value & 25456277e832SShreyas NC SKL_PIN_COUNT_MASK) >> 4; 25466277e832SShreyas NC 25476277e832SShreyas NC break; 25486277e832SShreyas NC 25496277e832SShreyas NC case SKL_TKN_U32_FMT_CH: 25506277e832SShreyas NC case SKL_TKN_U32_FMT_FREQ: 25516277e832SShreyas NC case SKL_TKN_U32_FMT_BIT_DEPTH: 25526277e832SShreyas NC case SKL_TKN_U32_FMT_SAMPLE_SIZE: 25536277e832SShreyas NC case SKL_TKN_U32_FMT_CH_CONFIG: 25546277e832SShreyas NC case SKL_TKN_U32_FMT_INTERLEAVE: 25556277e832SShreyas NC case SKL_TKN_U32_FMT_SAMPLE_TYPE: 25566277e832SShreyas NC case SKL_TKN_U32_FMT_CH_MAP: 2557f6fa56e2SRamesh Babu ret = skl_tplg_widget_fill_fmt(dev, iface, tkn_elem->token, 25586277e832SShreyas NC tkn_elem->value, dir, pin_index); 25596277e832SShreyas NC 25606277e832SShreyas NC if (ret < 0) 25616277e832SShreyas NC return ret; 25626277e832SShreyas NC 25636277e832SShreyas NC break; 25646277e832SShreyas NC 25656277e832SShreyas NC case SKL_TKN_U32_PIN_MOD_ID: 25666277e832SShreyas NC case SKL_TKN_U32_PIN_INST_ID: 2567d9561474SSriram Periyasamy case SKL_TKN_UUID: 25686277e832SShreyas NC ret = skl_tplg_fill_pins_info(dev, 25696277e832SShreyas NC mconfig, tkn_elem, dir, 25706277e832SShreyas NC pin_index); 25716277e832SShreyas NC if (ret < 0) 25726277e832SShreyas NC return ret; 25736277e832SShreyas NC 25746277e832SShreyas NC break; 25756277e832SShreyas NC 25766277e832SShreyas NC case SKL_TKN_U32_CAPS_SIZE: 25776277e832SShreyas NC mconfig->formats_config.caps_size = 25786277e832SShreyas NC tkn_elem->value; 25796277e832SShreyas NC 25806277e832SShreyas NC break; 25816277e832SShreyas NC 2582133e6e5cSShreyas NC case SKL_TKN_U32_CAPS_SET_PARAMS: 2583133e6e5cSShreyas NC mconfig->formats_config.set_params = 2584133e6e5cSShreyas NC tkn_elem->value; 2585133e6e5cSShreyas NC break; 2586133e6e5cSShreyas NC 2587133e6e5cSShreyas NC case SKL_TKN_U32_CAPS_PARAMS_ID: 2588133e6e5cSShreyas NC mconfig->formats_config.param_id = 2589133e6e5cSShreyas NC tkn_elem->value; 2590133e6e5cSShreyas NC break; 2591133e6e5cSShreyas NC 25926277e832SShreyas NC case SKL_TKN_U32_PROC_DOMAIN: 25936277e832SShreyas NC mconfig->domain = 25946277e832SShreyas NC tkn_elem->value; 25956277e832SShreyas NC 25966277e832SShreyas NC break; 25976277e832SShreyas NC 2598939df3adSRamesh Babu case SKL_TKN_U32_DMA_BUF_SIZE: 2599939df3adSRamesh Babu mconfig->dma_buffer_size = tkn_elem->value; 2600939df3adSRamesh Babu break; 2601939df3adSRamesh Babu 26026277e832SShreyas NC case SKL_TKN_U8_IN_PIN_TYPE: 26036277e832SShreyas NC case SKL_TKN_U8_OUT_PIN_TYPE: 26046277e832SShreyas NC case SKL_TKN_U8_CONN_TYPE: 26056277e832SShreyas NC break; 26066277e832SShreyas NC 26076277e832SShreyas NC default: 26086277e832SShreyas NC dev_err(dev, "Token %d not handled\n", 26096277e832SShreyas NC tkn_elem->token); 26106277e832SShreyas NC return -EINVAL; 26116277e832SShreyas NC } 26126277e832SShreyas NC 26136277e832SShreyas NC tkn_count++; 26146277e832SShreyas NC 26156277e832SShreyas NC return tkn_count; 26166277e832SShreyas NC } 26176277e832SShreyas NC 26186277e832SShreyas NC /* 26196277e832SShreyas NC * Parse the vendor array for specific tokens to construct 26206277e832SShreyas NC * module private data 26216277e832SShreyas NC */ 26226277e832SShreyas NC static int skl_tplg_get_tokens(struct device *dev, 2623*bcc2a2dcSCezary Rojewski char *pvt_data, struct skl_dev *skl, 26246277e832SShreyas NC struct skl_module_cfg *mconfig, int block_size) 26256277e832SShreyas NC { 26266277e832SShreyas NC struct snd_soc_tplg_vendor_array *array; 26276277e832SShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem; 26286277e832SShreyas NC int tkn_count = 0, ret; 26296277e832SShreyas NC int off = 0, tuple_size = 0; 2630d9561474SSriram Periyasamy bool is_module_guid = true; 26316277e832SShreyas NC 26326277e832SShreyas NC if (block_size <= 0) 26336277e832SShreyas NC return -EINVAL; 26346277e832SShreyas NC 26356277e832SShreyas NC while (tuple_size < block_size) { 26366277e832SShreyas NC array = (struct snd_soc_tplg_vendor_array *)(pvt_data + off); 26376277e832SShreyas NC 26386277e832SShreyas NC off += array->size; 26396277e832SShreyas NC 26406277e832SShreyas NC switch (array->type) { 26416277e832SShreyas NC case SND_SOC_TPLG_TUPLE_TYPE_STRING: 2642ecd286a9SColin Ian King dev_warn(dev, "no string tokens expected for skl tplg\n"); 26436277e832SShreyas NC continue; 26446277e832SShreyas NC 26456277e832SShreyas NC case SND_SOC_TPLG_TUPLE_TYPE_UUID: 2646d9561474SSriram Periyasamy if (is_module_guid) { 26479e0784d0SAndy Shevchenko ret = skl_tplg_get_uuid(dev, (guid_t *)mconfig->guid, 264822ebd666SSriram Periyasamy array->uuid); 2649d9561474SSriram Periyasamy is_module_guid = false; 2650d9561474SSriram Periyasamy } else { 2651d9561474SSriram Periyasamy ret = skl_tplg_get_token(dev, array->value, skl, 2652d9561474SSriram Periyasamy mconfig); 2653d9561474SSriram Periyasamy } 2654d9561474SSriram Periyasamy 26556277e832SShreyas NC if (ret < 0) 26566277e832SShreyas NC return ret; 26576277e832SShreyas NC 26586277e832SShreyas NC tuple_size += sizeof(*array->uuid); 26596277e832SShreyas NC 26606277e832SShreyas NC continue; 26616277e832SShreyas NC 26626277e832SShreyas NC default: 26636277e832SShreyas NC tkn_elem = array->value; 26646277e832SShreyas NC tkn_count = 0; 26656277e832SShreyas NC break; 26666277e832SShreyas NC } 26676277e832SShreyas NC 26686277e832SShreyas NC while (tkn_count <= (array->num_elems - 1)) { 26696277e832SShreyas NC ret = skl_tplg_get_token(dev, tkn_elem, 26706277e832SShreyas NC skl, mconfig); 26716277e832SShreyas NC 26726277e832SShreyas NC if (ret < 0) 26736277e832SShreyas NC return ret; 26746277e832SShreyas NC 26756277e832SShreyas NC tkn_count = tkn_count + ret; 26766277e832SShreyas NC tkn_elem++; 26776277e832SShreyas NC } 26786277e832SShreyas NC 26796277e832SShreyas NC tuple_size += tkn_count * sizeof(*tkn_elem); 26806277e832SShreyas NC } 26816277e832SShreyas NC 2682133e6e5cSShreyas NC return off; 26836277e832SShreyas NC } 26846277e832SShreyas NC 26856277e832SShreyas NC /* 26866277e832SShreyas NC * Every data block is preceded by a descriptor to read the number 26876277e832SShreyas NC * of data blocks, they type of the block and it's size 26886277e832SShreyas NC */ 26896277e832SShreyas NC static int skl_tplg_get_desc_blocks(struct device *dev, 26906277e832SShreyas NC struct snd_soc_tplg_vendor_array *array) 26916277e832SShreyas NC { 26926277e832SShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem; 26936277e832SShreyas NC 26946277e832SShreyas NC tkn_elem = array->value; 26956277e832SShreyas NC 26966277e832SShreyas NC switch (tkn_elem->token) { 26976277e832SShreyas NC case SKL_TKN_U8_NUM_BLOCKS: 26986277e832SShreyas NC case SKL_TKN_U8_BLOCK_TYPE: 26996277e832SShreyas NC case SKL_TKN_U16_BLOCK_SIZE: 27006277e832SShreyas NC return tkn_elem->value; 27016277e832SShreyas NC 27026277e832SShreyas NC default: 2703ecd286a9SColin Ian King dev_err(dev, "Invalid descriptor token %d\n", tkn_elem->token); 27046277e832SShreyas NC break; 27056277e832SShreyas NC } 27066277e832SShreyas NC 27076277e832SShreyas NC return -EINVAL; 27086277e832SShreyas NC } 27096277e832SShreyas NC 2710ac9391daSGuenter Roeck /* Functions to parse private data from configuration file format v4 */ 2711ac9391daSGuenter Roeck 2712ac9391daSGuenter Roeck /* 2713ac9391daSGuenter Roeck * Add pipeline from topology binary into driver pipeline list 2714ac9391daSGuenter Roeck * 2715ac9391daSGuenter Roeck * If already added we return that instance 2716ac9391daSGuenter Roeck * Otherwise we create a new instance and add into driver list 2717ac9391daSGuenter Roeck */ 2718ac9391daSGuenter Roeck static int skl_tplg_add_pipe_v4(struct device *dev, 2719*bcc2a2dcSCezary Rojewski struct skl_module_cfg *mconfig, struct skl_dev *skl, 2720ac9391daSGuenter Roeck struct skl_dfw_v4_pipe *dfw_pipe) 2721ac9391daSGuenter Roeck { 2722ac9391daSGuenter Roeck struct skl_pipeline *ppl; 2723ac9391daSGuenter Roeck struct skl_pipe *pipe; 2724ac9391daSGuenter Roeck struct skl_pipe_params *params; 2725ac9391daSGuenter Roeck 2726ac9391daSGuenter Roeck list_for_each_entry(ppl, &skl->ppl_list, node) { 2727ac9391daSGuenter Roeck if (ppl->pipe->ppl_id == dfw_pipe->pipe_id) { 2728ac9391daSGuenter Roeck mconfig->pipe = ppl->pipe; 2729ac9391daSGuenter Roeck return 0; 2730ac9391daSGuenter Roeck } 2731ac9391daSGuenter Roeck } 2732ac9391daSGuenter Roeck 2733ac9391daSGuenter Roeck ppl = devm_kzalloc(dev, sizeof(*ppl), GFP_KERNEL); 2734ac9391daSGuenter Roeck if (!ppl) 2735ac9391daSGuenter Roeck return -ENOMEM; 2736ac9391daSGuenter Roeck 2737ac9391daSGuenter Roeck pipe = devm_kzalloc(dev, sizeof(*pipe), GFP_KERNEL); 2738ac9391daSGuenter Roeck if (!pipe) 2739ac9391daSGuenter Roeck return -ENOMEM; 2740ac9391daSGuenter Roeck 2741ac9391daSGuenter Roeck params = devm_kzalloc(dev, sizeof(*params), GFP_KERNEL); 2742ac9391daSGuenter Roeck if (!params) 2743ac9391daSGuenter Roeck return -ENOMEM; 2744ac9391daSGuenter Roeck 2745ac9391daSGuenter Roeck pipe->ppl_id = dfw_pipe->pipe_id; 2746ac9391daSGuenter Roeck pipe->memory_pages = dfw_pipe->memory_pages; 2747ac9391daSGuenter Roeck pipe->pipe_priority = dfw_pipe->pipe_priority; 2748ac9391daSGuenter Roeck pipe->conn_type = dfw_pipe->conn_type; 2749ac9391daSGuenter Roeck pipe->state = SKL_PIPE_INVALID; 2750ac9391daSGuenter Roeck pipe->p_params = params; 2751ac9391daSGuenter Roeck INIT_LIST_HEAD(&pipe->w_list); 2752ac9391daSGuenter Roeck 2753ac9391daSGuenter Roeck ppl->pipe = pipe; 2754ac9391daSGuenter Roeck list_add(&ppl->node, &skl->ppl_list); 2755ac9391daSGuenter Roeck 2756ac9391daSGuenter Roeck mconfig->pipe = pipe; 2757ac9391daSGuenter Roeck 2758ac9391daSGuenter Roeck return 0; 2759ac9391daSGuenter Roeck } 2760ac9391daSGuenter Roeck 2761ac9391daSGuenter Roeck static void skl_fill_module_pin_info_v4(struct skl_dfw_v4_module_pin *dfw_pin, 2762ac9391daSGuenter Roeck struct skl_module_pin *m_pin, 2763ac9391daSGuenter Roeck bool is_dynamic, int max_pin) 2764ac9391daSGuenter Roeck { 2765ac9391daSGuenter Roeck int i; 2766ac9391daSGuenter Roeck 2767ac9391daSGuenter Roeck for (i = 0; i < max_pin; i++) { 2768ac9391daSGuenter Roeck m_pin[i].id.module_id = dfw_pin[i].module_id; 2769ac9391daSGuenter Roeck m_pin[i].id.instance_id = dfw_pin[i].instance_id; 2770ac9391daSGuenter Roeck m_pin[i].in_use = false; 2771ac9391daSGuenter Roeck m_pin[i].is_dynamic = is_dynamic; 2772ac9391daSGuenter Roeck m_pin[i].pin_state = SKL_PIN_UNBIND; 2773ac9391daSGuenter Roeck } 2774ac9391daSGuenter Roeck } 2775ac9391daSGuenter Roeck 2776ac9391daSGuenter Roeck static void skl_tplg_fill_fmt_v4(struct skl_module_pin_fmt *dst_fmt, 2777ac9391daSGuenter Roeck struct skl_dfw_v4_module_fmt *src_fmt, 2778ac9391daSGuenter Roeck int pins) 2779ac9391daSGuenter Roeck { 2780ac9391daSGuenter Roeck int i; 2781ac9391daSGuenter Roeck 2782ac9391daSGuenter Roeck for (i = 0; i < pins; i++) { 2783ac9391daSGuenter Roeck dst_fmt[i].fmt.channels = src_fmt[i].channels; 2784ac9391daSGuenter Roeck dst_fmt[i].fmt.s_freq = src_fmt[i].freq; 2785ac9391daSGuenter Roeck dst_fmt[i].fmt.bit_depth = src_fmt[i].bit_depth; 2786ac9391daSGuenter Roeck dst_fmt[i].fmt.valid_bit_depth = src_fmt[i].valid_bit_depth; 2787ac9391daSGuenter Roeck dst_fmt[i].fmt.ch_cfg = src_fmt[i].ch_cfg; 2788ac9391daSGuenter Roeck dst_fmt[i].fmt.ch_map = src_fmt[i].ch_map; 2789ac9391daSGuenter Roeck dst_fmt[i].fmt.interleaving_style = 2790ac9391daSGuenter Roeck src_fmt[i].interleaving_style; 2791ac9391daSGuenter Roeck dst_fmt[i].fmt.sample_type = src_fmt[i].sample_type; 2792ac9391daSGuenter Roeck } 2793ac9391daSGuenter Roeck } 2794ac9391daSGuenter Roeck 2795ac9391daSGuenter Roeck static int skl_tplg_get_pvt_data_v4(struct snd_soc_tplg_dapm_widget *tplg_w, 2796*bcc2a2dcSCezary Rojewski struct skl_dev *skl, struct device *dev, 2797ac9391daSGuenter Roeck struct skl_module_cfg *mconfig) 2798ac9391daSGuenter Roeck { 2799ac9391daSGuenter Roeck struct skl_dfw_v4_module *dfw = 2800ac9391daSGuenter Roeck (struct skl_dfw_v4_module *)tplg_w->priv.data; 2801ac9391daSGuenter Roeck int ret; 2802ac9391daSGuenter Roeck 2803ac9391daSGuenter Roeck dev_dbg(dev, "Parsing Skylake v4 widget topology data\n"); 2804ac9391daSGuenter Roeck 2805ac9391daSGuenter Roeck ret = guid_parse(dfw->uuid, (guid_t *)mconfig->guid); 2806ac9391daSGuenter Roeck if (ret) 2807ac9391daSGuenter Roeck return ret; 2808ac9391daSGuenter Roeck mconfig->id.module_id = -1; 2809ac9391daSGuenter Roeck mconfig->id.instance_id = dfw->instance_id; 2810ac9391daSGuenter Roeck mconfig->module->resources[0].cps = dfw->max_mcps; 2811ac9391daSGuenter Roeck mconfig->module->resources[0].ibs = dfw->ibs; 2812ac9391daSGuenter Roeck mconfig->module->resources[0].obs = dfw->obs; 2813ac9391daSGuenter Roeck mconfig->core_id = dfw->core_id; 2814ac9391daSGuenter Roeck mconfig->module->max_input_pins = dfw->max_in_queue; 2815ac9391daSGuenter Roeck mconfig->module->max_output_pins = dfw->max_out_queue; 2816ac9391daSGuenter Roeck mconfig->module->loadable = dfw->is_loadable; 2817ac9391daSGuenter Roeck skl_tplg_fill_fmt_v4(mconfig->module->formats[0].inputs, dfw->in_fmt, 2818ac9391daSGuenter Roeck MAX_IN_QUEUE); 2819ac9391daSGuenter Roeck skl_tplg_fill_fmt_v4(mconfig->module->formats[0].outputs, dfw->out_fmt, 2820ac9391daSGuenter Roeck MAX_OUT_QUEUE); 2821ac9391daSGuenter Roeck 2822ac9391daSGuenter Roeck mconfig->params_fixup = dfw->params_fixup; 2823ac9391daSGuenter Roeck mconfig->converter = dfw->converter; 2824ac9391daSGuenter Roeck mconfig->m_type = dfw->module_type; 2825ac9391daSGuenter Roeck mconfig->vbus_id = dfw->vbus_id; 2826ac9391daSGuenter Roeck mconfig->module->resources[0].is_pages = dfw->mem_pages; 2827ac9391daSGuenter Roeck 2828ac9391daSGuenter Roeck ret = skl_tplg_add_pipe_v4(dev, mconfig, skl, &dfw->pipe); 2829ac9391daSGuenter Roeck if (ret) 2830ac9391daSGuenter Roeck return ret; 2831ac9391daSGuenter Roeck 2832ac9391daSGuenter Roeck mconfig->dev_type = dfw->dev_type; 2833ac9391daSGuenter Roeck mconfig->hw_conn_type = dfw->hw_conn_type; 2834ac9391daSGuenter Roeck mconfig->time_slot = dfw->time_slot; 2835ac9391daSGuenter Roeck mconfig->formats_config.caps_size = dfw->caps.caps_size; 2836ac9391daSGuenter Roeck 2837a86854d0SKees Cook mconfig->m_in_pin = devm_kcalloc(dev, 2838a86854d0SKees Cook MAX_IN_QUEUE, sizeof(*mconfig->m_in_pin), 2839ac9391daSGuenter Roeck GFP_KERNEL); 2840ac9391daSGuenter Roeck if (!mconfig->m_in_pin) 2841ac9391daSGuenter Roeck return -ENOMEM; 2842ac9391daSGuenter Roeck 2843a86854d0SKees Cook mconfig->m_out_pin = devm_kcalloc(dev, 2844a86854d0SKees Cook MAX_OUT_QUEUE, sizeof(*mconfig->m_out_pin), 2845ac9391daSGuenter Roeck GFP_KERNEL); 2846ac9391daSGuenter Roeck if (!mconfig->m_out_pin) 2847ac9391daSGuenter Roeck return -ENOMEM; 2848ac9391daSGuenter Roeck 2849ac9391daSGuenter Roeck skl_fill_module_pin_info_v4(dfw->in_pin, mconfig->m_in_pin, 2850ac9391daSGuenter Roeck dfw->is_dynamic_in_pin, 2851ac9391daSGuenter Roeck mconfig->module->max_input_pins); 2852ac9391daSGuenter Roeck skl_fill_module_pin_info_v4(dfw->out_pin, mconfig->m_out_pin, 2853ac9391daSGuenter Roeck dfw->is_dynamic_out_pin, 2854ac9391daSGuenter Roeck mconfig->module->max_output_pins); 2855ac9391daSGuenter Roeck 2856ac9391daSGuenter Roeck if (mconfig->formats_config.caps_size) { 2857ac9391daSGuenter Roeck mconfig->formats_config.set_params = dfw->caps.set_params; 2858ac9391daSGuenter Roeck mconfig->formats_config.param_id = dfw->caps.param_id; 2859ac9391daSGuenter Roeck mconfig->formats_config.caps = 2860ac9391daSGuenter Roeck devm_kzalloc(dev, mconfig->formats_config.caps_size, 2861ac9391daSGuenter Roeck GFP_KERNEL); 2862ac9391daSGuenter Roeck if (!mconfig->formats_config.caps) 2863ac9391daSGuenter Roeck return -ENOMEM; 2864ac9391daSGuenter Roeck memcpy(mconfig->formats_config.caps, dfw->caps.caps, 2865ac9391daSGuenter Roeck dfw->caps.caps_size); 2866ac9391daSGuenter Roeck } 2867ac9391daSGuenter Roeck 2868ac9391daSGuenter Roeck return 0; 2869ac9391daSGuenter Roeck } 2870ac9391daSGuenter Roeck 28716277e832SShreyas NC /* 28726277e832SShreyas NC * Parse the private data for the token and corresponding value. 28736277e832SShreyas NC * The private data can have multiple data blocks. So, a data block 28746277e832SShreyas NC * is preceded by a descriptor for number of blocks and a descriptor 28756277e832SShreyas NC * for the type and size of the suceeding data block. 28766277e832SShreyas NC */ 28776277e832SShreyas NC static int skl_tplg_get_pvt_data(struct snd_soc_tplg_dapm_widget *tplg_w, 2878*bcc2a2dcSCezary Rojewski struct skl_dev *skl, struct device *dev, 28796277e832SShreyas NC struct skl_module_cfg *mconfig) 28806277e832SShreyas NC { 28816277e832SShreyas NC struct snd_soc_tplg_vendor_array *array; 28826277e832SShreyas NC int num_blocks, block_size = 0, block_type, off = 0; 28836277e832SShreyas NC char *data; 28846277e832SShreyas NC int ret; 28856277e832SShreyas NC 2886ac9391daSGuenter Roeck /* 2887ac9391daSGuenter Roeck * v4 configuration files have a valid UUID at the start of 2888ac9391daSGuenter Roeck * the widget's private data. 2889ac9391daSGuenter Roeck */ 2890ac9391daSGuenter Roeck if (uuid_is_valid((char *)tplg_w->priv.data)) 2891ac9391daSGuenter Roeck return skl_tplg_get_pvt_data_v4(tplg_w, skl, dev, mconfig); 2892ac9391daSGuenter Roeck 28936277e832SShreyas NC /* Read the NUM_DATA_BLOCKS descriptor */ 28946277e832SShreyas NC array = (struct snd_soc_tplg_vendor_array *)tplg_w->priv.data; 28956277e832SShreyas NC ret = skl_tplg_get_desc_blocks(dev, array); 28966277e832SShreyas NC if (ret < 0) 28976277e832SShreyas NC return ret; 28986277e832SShreyas NC num_blocks = ret; 28996277e832SShreyas NC 29006277e832SShreyas NC off += array->size; 29016277e832SShreyas NC /* Read the BLOCK_TYPE and BLOCK_SIZE descriptor */ 29026277e832SShreyas NC while (num_blocks > 0) { 2903133e6e5cSShreyas NC array = (struct snd_soc_tplg_vendor_array *) 2904133e6e5cSShreyas NC (tplg_w->priv.data + off); 2905133e6e5cSShreyas NC 29066277e832SShreyas NC ret = skl_tplg_get_desc_blocks(dev, array); 29076277e832SShreyas NC 29086277e832SShreyas NC if (ret < 0) 29096277e832SShreyas NC return ret; 29106277e832SShreyas NC block_type = ret; 29116277e832SShreyas NC off += array->size; 29126277e832SShreyas NC 29136277e832SShreyas NC array = (struct snd_soc_tplg_vendor_array *) 29146277e832SShreyas NC (tplg_w->priv.data + off); 29156277e832SShreyas NC 29166277e832SShreyas NC ret = skl_tplg_get_desc_blocks(dev, array); 29176277e832SShreyas NC 29186277e832SShreyas NC if (ret < 0) 29196277e832SShreyas NC return ret; 29206277e832SShreyas NC block_size = ret; 29216277e832SShreyas NC off += array->size; 29226277e832SShreyas NC 29236277e832SShreyas NC array = (struct snd_soc_tplg_vendor_array *) 29246277e832SShreyas NC (tplg_w->priv.data + off); 29256277e832SShreyas NC 29266277e832SShreyas NC data = (tplg_w->priv.data + off); 29276277e832SShreyas NC 29286277e832SShreyas NC if (block_type == SKL_TYPE_TUPLE) { 29296277e832SShreyas NC ret = skl_tplg_get_tokens(dev, data, 29306277e832SShreyas NC skl, mconfig, block_size); 29316277e832SShreyas NC 29326277e832SShreyas NC if (ret < 0) 29336277e832SShreyas NC return ret; 29346277e832SShreyas NC 29356277e832SShreyas NC --num_blocks; 29366277e832SShreyas NC } else { 29376277e832SShreyas NC if (mconfig->formats_config.caps_size > 0) 29386277e832SShreyas NC memcpy(mconfig->formats_config.caps, data, 29396277e832SShreyas NC mconfig->formats_config.caps_size); 29406277e832SShreyas NC --num_blocks; 2941133e6e5cSShreyas NC ret = mconfig->formats_config.caps_size; 29426277e832SShreyas NC } 2943133e6e5cSShreyas NC off += ret; 29446277e832SShreyas NC } 29456277e832SShreyas NC 29466277e832SShreyas NC return 0; 29474cd9899fSHardik T Shah } 29484cd9899fSHardik T Shah 294956b03b4cSKuninori Morimoto static void skl_clear_pin_config(struct snd_soc_component *component, 2950fe3f4442SDharageswari R struct snd_soc_dapm_widget *w) 2951fe3f4442SDharageswari R { 2952fe3f4442SDharageswari R int i; 2953fe3f4442SDharageswari R struct skl_module_cfg *mconfig; 2954fe3f4442SDharageswari R struct skl_pipe *pipe; 2955fe3f4442SDharageswari R 295656b03b4cSKuninori Morimoto if (!strncmp(w->dapm->component->name, component->name, 295756b03b4cSKuninori Morimoto strlen(component->name))) { 2958fe3f4442SDharageswari R mconfig = w->priv; 2959fe3f4442SDharageswari R pipe = mconfig->pipe; 2960f6fa56e2SRamesh Babu for (i = 0; i < mconfig->module->max_input_pins; i++) { 2961fe3f4442SDharageswari R mconfig->m_in_pin[i].in_use = false; 2962fe3f4442SDharageswari R mconfig->m_in_pin[i].pin_state = SKL_PIN_UNBIND; 2963fe3f4442SDharageswari R } 2964f6fa56e2SRamesh Babu for (i = 0; i < mconfig->module->max_output_pins; i++) { 2965fe3f4442SDharageswari R mconfig->m_out_pin[i].in_use = false; 2966fe3f4442SDharageswari R mconfig->m_out_pin[i].pin_state = SKL_PIN_UNBIND; 2967fe3f4442SDharageswari R } 2968fe3f4442SDharageswari R pipe->state = SKL_PIPE_INVALID; 2969fe3f4442SDharageswari R mconfig->m_state = SKL_MODULE_UNINIT; 2970fe3f4442SDharageswari R } 2971fe3f4442SDharageswari R } 2972fe3f4442SDharageswari R 2973*bcc2a2dcSCezary Rojewski void skl_cleanup_resources(struct skl_dev *skl) 2974fe3f4442SDharageswari R { 297556b03b4cSKuninori Morimoto struct snd_soc_component *soc_component = skl->component; 2976fe3f4442SDharageswari R struct snd_soc_dapm_widget *w; 2977fe3f4442SDharageswari R struct snd_soc_card *card; 2978fe3f4442SDharageswari R 297956b03b4cSKuninori Morimoto if (soc_component == NULL) 2980fe3f4442SDharageswari R return; 2981fe3f4442SDharageswari R 298256b03b4cSKuninori Morimoto card = soc_component->card; 2983fe3f4442SDharageswari R if (!card || !card->instantiated) 2984fe3f4442SDharageswari R return; 2985fe3f4442SDharageswari R 2986fe3f4442SDharageswari R skl->resource.mem = 0; 2987fe3f4442SDharageswari R skl->resource.mcps = 0; 2988fe3f4442SDharageswari R 2989fe3f4442SDharageswari R list_for_each_entry(w, &card->widgets, list) { 2990*bcc2a2dcSCezary Rojewski if (is_skl_dsp_widget_type(w, skl->dev) && w->priv != NULL) 299156b03b4cSKuninori Morimoto skl_clear_pin_config(soc_component, w); 2992fe3f4442SDharageswari R } 2993fe3f4442SDharageswari R 2994*bcc2a2dcSCezary Rojewski skl_clear_module_cnt(skl->dsp); 2995fe3f4442SDharageswari R } 2996fe3f4442SDharageswari R 29973af36706SVinod Koul /* 29983af36706SVinod Koul * Topology core widget load callback 29993af36706SVinod Koul * 30003af36706SVinod Koul * This is used to save the private data for each widget which gives 30013af36706SVinod Koul * information to the driver about module and pipeline parameters which DSP 30023af36706SVinod Koul * FW expects like ids, resource values, formats etc 30033af36706SVinod Koul */ 3004c60b613aSLiam Girdwood static int skl_tplg_widget_load(struct snd_soc_component *cmpnt, int index, 30053af36706SVinod Koul struct snd_soc_dapm_widget *w, 30063af36706SVinod Koul struct snd_soc_tplg_dapm_widget *tplg_w) 30073af36706SVinod Koul { 30083af36706SVinod Koul int ret; 300976f56faeSRakesh Ughreja struct hdac_bus *bus = snd_soc_component_get_drvdata(cmpnt); 3010*bcc2a2dcSCezary Rojewski struct skl_dev *skl = bus_to_skl(bus); 30113af36706SVinod Koul struct skl_module_cfg *mconfig; 30123af36706SVinod Koul 30133af36706SVinod Koul if (!tplg_w->priv.size) 30143af36706SVinod Koul goto bind_event; 30153af36706SVinod Koul 30163af36706SVinod Koul mconfig = devm_kzalloc(bus->dev, sizeof(*mconfig), GFP_KERNEL); 30173af36706SVinod Koul 30183af36706SVinod Koul if (!mconfig) 30193af36706SVinod Koul return -ENOMEM; 30203af36706SVinod Koul 3021f6fa56e2SRamesh Babu if (skl->nr_modules == 0) { 3022f6fa56e2SRamesh Babu mconfig->module = devm_kzalloc(bus->dev, 3023f6fa56e2SRamesh Babu sizeof(*mconfig->module), GFP_KERNEL); 3024f6fa56e2SRamesh Babu if (!mconfig->module) 3025f6fa56e2SRamesh Babu return -ENOMEM; 3026f6fa56e2SRamesh Babu } 3027f6fa56e2SRamesh Babu 30283af36706SVinod Koul w->priv = mconfig; 302909305da9SShreyas NC 3030b7c50555SVinod Koul /* 3031b7c50555SVinod Koul * module binary can be loaded later, so set it to query when 3032b7c50555SVinod Koul * module is load for a use case 3033b7c50555SVinod Koul */ 3034b7c50555SVinod Koul mconfig->id.module_id = -1; 30354cd9899fSHardik T Shah 30366277e832SShreyas NC /* Parse private data for tuples */ 30376277e832SShreyas NC ret = skl_tplg_get_pvt_data(tplg_w, skl, bus->dev, mconfig); 30386277e832SShreyas NC if (ret < 0) 30396277e832SShreyas NC return ret; 3040d14700a0SVinod Koul 3041d14700a0SVinod Koul skl_debug_init_module(skl->debugfs, w, mconfig); 3042d14700a0SVinod Koul 30433af36706SVinod Koul bind_event: 30443af36706SVinod Koul if (tplg_w->event_type == 0) { 30453373f716SVinod Koul dev_dbg(bus->dev, "ASoC: No event handler required\n"); 30463af36706SVinod Koul return 0; 30473af36706SVinod Koul } 30483af36706SVinod Koul 30493af36706SVinod Koul ret = snd_soc_tplg_widget_bind_event(w, skl_tplg_widget_ops, 3050b663a8c5SJeeja KP ARRAY_SIZE(skl_tplg_widget_ops), 3051b663a8c5SJeeja KP tplg_w->event_type); 30523af36706SVinod Koul 30533af36706SVinod Koul if (ret) { 30543af36706SVinod Koul dev_err(bus->dev, "%s: No matching event handlers found for %d\n", 30553af36706SVinod Koul __func__, tplg_w->event_type); 30563af36706SVinod Koul return -EINVAL; 30573af36706SVinod Koul } 30583af36706SVinod Koul 30593af36706SVinod Koul return 0; 30603af36706SVinod Koul } 30613af36706SVinod Koul 3062140adfbaSJeeja KP static int skl_init_algo_data(struct device *dev, struct soc_bytes_ext *be, 3063140adfbaSJeeja KP struct snd_soc_tplg_bytes_control *bc) 3064140adfbaSJeeja KP { 3065140adfbaSJeeja KP struct skl_algo_data *ac; 3066140adfbaSJeeja KP struct skl_dfw_algo_data *dfw_ac = 3067140adfbaSJeeja KP (struct skl_dfw_algo_data *)bc->priv.data; 3068140adfbaSJeeja KP 3069140adfbaSJeeja KP ac = devm_kzalloc(dev, sizeof(*ac), GFP_KERNEL); 3070140adfbaSJeeja KP if (!ac) 3071140adfbaSJeeja KP return -ENOMEM; 3072140adfbaSJeeja KP 3073140adfbaSJeeja KP /* Fill private data */ 3074140adfbaSJeeja KP ac->max = dfw_ac->max; 3075140adfbaSJeeja KP ac->param_id = dfw_ac->param_id; 3076140adfbaSJeeja KP ac->set_params = dfw_ac->set_params; 30770d682104SDharageswari R ac->size = dfw_ac->max; 3078140adfbaSJeeja KP 3079140adfbaSJeeja KP if (ac->max) { 3080431b67c2SPierre-Louis Bossart ac->params = devm_kzalloc(dev, ac->max, GFP_KERNEL); 3081140adfbaSJeeja KP if (!ac->params) 3082140adfbaSJeeja KP return -ENOMEM; 3083140adfbaSJeeja KP 3084140adfbaSJeeja KP memcpy(ac->params, dfw_ac->params, ac->max); 3085140adfbaSJeeja KP } 3086140adfbaSJeeja KP 3087140adfbaSJeeja KP be->dobj.private = ac; 3088140adfbaSJeeja KP return 0; 3089140adfbaSJeeja KP } 3090140adfbaSJeeja KP 30917a1b749bSDharageswari R static int skl_init_enum_data(struct device *dev, struct soc_enum *se, 30927a1b749bSDharageswari R struct snd_soc_tplg_enum_control *ec) 30937a1b749bSDharageswari R { 30947a1b749bSDharageswari R 30957a1b749bSDharageswari R void *data; 30967a1b749bSDharageswari R 30977a1b749bSDharageswari R if (ec->priv.size) { 30987a1b749bSDharageswari R data = devm_kzalloc(dev, sizeof(ec->priv.size), GFP_KERNEL); 30997a1b749bSDharageswari R if (!data) 31007a1b749bSDharageswari R return -ENOMEM; 31017a1b749bSDharageswari R memcpy(data, ec->priv.data, ec->priv.size); 31027a1b749bSDharageswari R se->dobj.private = data; 31037a1b749bSDharageswari R } 31047a1b749bSDharageswari R 31057a1b749bSDharageswari R return 0; 31067a1b749bSDharageswari R 31077a1b749bSDharageswari R } 31087a1b749bSDharageswari R 3109140adfbaSJeeja KP static int skl_tplg_control_load(struct snd_soc_component *cmpnt, 3110c60b613aSLiam Girdwood int index, 3111140adfbaSJeeja KP struct snd_kcontrol_new *kctl, 3112140adfbaSJeeja KP struct snd_soc_tplg_ctl_hdr *hdr) 3113140adfbaSJeeja KP { 3114140adfbaSJeeja KP struct soc_bytes_ext *sb; 3115140adfbaSJeeja KP struct snd_soc_tplg_bytes_control *tplg_bc; 31167a1b749bSDharageswari R struct snd_soc_tplg_enum_control *tplg_ec; 311776f56faeSRakesh Ughreja struct hdac_bus *bus = snd_soc_component_get_drvdata(cmpnt); 31187a1b749bSDharageswari R struct soc_enum *se; 3119140adfbaSJeeja KP 3120140adfbaSJeeja KP switch (hdr->ops.info) { 3121140adfbaSJeeja KP case SND_SOC_TPLG_CTL_BYTES: 3122140adfbaSJeeja KP tplg_bc = container_of(hdr, 3123140adfbaSJeeja KP struct snd_soc_tplg_bytes_control, hdr); 3124140adfbaSJeeja KP if (kctl->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { 3125140adfbaSJeeja KP sb = (struct soc_bytes_ext *)kctl->private_value; 3126140adfbaSJeeja KP if (tplg_bc->priv.size) 3127140adfbaSJeeja KP return skl_init_algo_data( 3128140adfbaSJeeja KP bus->dev, sb, tplg_bc); 3129140adfbaSJeeja KP } 3130140adfbaSJeeja KP break; 3131140adfbaSJeeja KP 31327a1b749bSDharageswari R case SND_SOC_TPLG_CTL_ENUM: 31337a1b749bSDharageswari R tplg_ec = container_of(hdr, 31347a1b749bSDharageswari R struct snd_soc_tplg_enum_control, hdr); 31357a1b749bSDharageswari R if (kctl->access & SNDRV_CTL_ELEM_ACCESS_READWRITE) { 31367a1b749bSDharageswari R se = (struct soc_enum *)kctl->private_value; 31377a1b749bSDharageswari R if (tplg_ec->priv.size) 31387a1b749bSDharageswari R return skl_init_enum_data(bus->dev, se, 31397a1b749bSDharageswari R tplg_ec); 31407a1b749bSDharageswari R } 31417a1b749bSDharageswari R break; 31427a1b749bSDharageswari R 3143140adfbaSJeeja KP default: 31444362934aSNaveen Manohar dev_dbg(bus->dev, "Control load not supported %d:%d:%d\n", 3145140adfbaSJeeja KP hdr->ops.get, hdr->ops.put, hdr->ops.info); 3146140adfbaSJeeja KP break; 3147140adfbaSJeeja KP } 3148140adfbaSJeeja KP 3149140adfbaSJeeja KP return 0; 3150140adfbaSJeeja KP } 3151140adfbaSJeeja KP 3152541070ceSShreyas NC static int skl_tplg_fill_str_mfest_tkn(struct device *dev, 3153541070ceSShreyas NC struct snd_soc_tplg_vendor_string_elem *str_elem, 3154*bcc2a2dcSCezary Rojewski struct skl_dev *skl) 3155541070ceSShreyas NC { 3156541070ceSShreyas NC int tkn_count = 0; 3157541070ceSShreyas NC static int ref_count; 3158541070ceSShreyas NC 3159541070ceSShreyas NC switch (str_elem->token) { 3160541070ceSShreyas NC case SKL_TKN_STR_LIB_NAME: 3161*bcc2a2dcSCezary Rojewski if (ref_count > skl->lib_count - 1) { 3162541070ceSShreyas NC ref_count = 0; 3163541070ceSShreyas NC return -EINVAL; 3164541070ceSShreyas NC } 3165541070ceSShreyas NC 3166*bcc2a2dcSCezary Rojewski strncpy(skl->lib_info[ref_count].name, 3167eee0e16fSJeeja KP str_elem->string, 3168*bcc2a2dcSCezary Rojewski ARRAY_SIZE(skl->lib_info[ref_count].name)); 3169541070ceSShreyas NC ref_count++; 3170541070ceSShreyas NC break; 3171541070ceSShreyas NC 3172541070ceSShreyas NC default: 3173ecd286a9SColin Ian King dev_err(dev, "Not a string token %d\n", str_elem->token); 3174541070ceSShreyas NC break; 3175541070ceSShreyas NC } 3176db6ed55dSShreyas NC tkn_count++; 3177541070ceSShreyas NC 3178541070ceSShreyas NC return tkn_count; 3179541070ceSShreyas NC } 3180541070ceSShreyas NC 3181541070ceSShreyas NC static int skl_tplg_get_str_tkn(struct device *dev, 3182541070ceSShreyas NC struct snd_soc_tplg_vendor_array *array, 3183*bcc2a2dcSCezary Rojewski struct skl_dev *skl) 3184541070ceSShreyas NC { 3185541070ceSShreyas NC int tkn_count = 0, ret; 3186541070ceSShreyas NC struct snd_soc_tplg_vendor_string_elem *str_elem; 3187541070ceSShreyas NC 3188541070ceSShreyas NC str_elem = (struct snd_soc_tplg_vendor_string_elem *)array->value; 3189541070ceSShreyas NC while (tkn_count < array->num_elems) { 3190eee0e16fSJeeja KP ret = skl_tplg_fill_str_mfest_tkn(dev, str_elem, skl); 3191541070ceSShreyas NC str_elem++; 3192541070ceSShreyas NC 3193541070ceSShreyas NC if (ret < 0) 3194541070ceSShreyas NC return ret; 3195541070ceSShreyas NC 3196541070ceSShreyas NC tkn_count = tkn_count + ret; 3197541070ceSShreyas NC } 3198541070ceSShreyas NC 3199541070ceSShreyas NC return tkn_count; 3200541070ceSShreyas NC } 3201541070ceSShreyas NC 3202db6ed55dSShreyas NC static int skl_tplg_manifest_fill_fmt(struct device *dev, 3203db6ed55dSShreyas NC struct skl_module_iface *fmt, 3204db6ed55dSShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem, 3205db6ed55dSShreyas NC u32 dir, int fmt_idx) 3206db6ed55dSShreyas NC { 3207db6ed55dSShreyas NC struct skl_module_pin_fmt *dst_fmt; 3208db6ed55dSShreyas NC struct skl_module_fmt *mod_fmt; 3209db6ed55dSShreyas NC int ret; 3210db6ed55dSShreyas NC 3211db6ed55dSShreyas NC if (!fmt) 3212db6ed55dSShreyas NC return -EINVAL; 3213db6ed55dSShreyas NC 3214db6ed55dSShreyas NC switch (dir) { 3215db6ed55dSShreyas NC case SKL_DIR_IN: 3216db6ed55dSShreyas NC dst_fmt = &fmt->inputs[fmt_idx]; 3217db6ed55dSShreyas NC break; 3218db6ed55dSShreyas NC 3219db6ed55dSShreyas NC case SKL_DIR_OUT: 3220db6ed55dSShreyas NC dst_fmt = &fmt->outputs[fmt_idx]; 3221db6ed55dSShreyas NC break; 3222db6ed55dSShreyas NC 3223db6ed55dSShreyas NC default: 3224db6ed55dSShreyas NC dev_err(dev, "Invalid direction: %d\n", dir); 3225db6ed55dSShreyas NC return -EINVAL; 3226db6ed55dSShreyas NC } 3227db6ed55dSShreyas NC 3228db6ed55dSShreyas NC mod_fmt = &dst_fmt->fmt; 3229db6ed55dSShreyas NC 3230db6ed55dSShreyas NC switch (tkn_elem->token) { 3231db6ed55dSShreyas NC case SKL_TKN_MM_U32_INTF_PIN_ID: 3232db6ed55dSShreyas NC dst_fmt->id = tkn_elem->value; 3233db6ed55dSShreyas NC break; 3234db6ed55dSShreyas NC 3235db6ed55dSShreyas NC default: 3236db6ed55dSShreyas NC ret = skl_tplg_fill_fmt(dev, mod_fmt, tkn_elem->token, 3237db6ed55dSShreyas NC tkn_elem->value); 3238db6ed55dSShreyas NC if (ret < 0) 3239db6ed55dSShreyas NC return ret; 3240db6ed55dSShreyas NC break; 3241db6ed55dSShreyas NC } 3242db6ed55dSShreyas NC 3243db6ed55dSShreyas NC return 0; 3244db6ed55dSShreyas NC } 3245db6ed55dSShreyas NC 3246db6ed55dSShreyas NC static int skl_tplg_fill_mod_info(struct device *dev, 3247db6ed55dSShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem, 3248db6ed55dSShreyas NC struct skl_module *mod) 3249db6ed55dSShreyas NC { 3250db6ed55dSShreyas NC 3251db6ed55dSShreyas NC if (!mod) 3252db6ed55dSShreyas NC return -EINVAL; 3253db6ed55dSShreyas NC 3254db6ed55dSShreyas NC switch (tkn_elem->token) { 3255db6ed55dSShreyas NC case SKL_TKN_U8_IN_PIN_TYPE: 3256db6ed55dSShreyas NC mod->input_pin_type = tkn_elem->value; 3257db6ed55dSShreyas NC break; 3258db6ed55dSShreyas NC 3259db6ed55dSShreyas NC case SKL_TKN_U8_OUT_PIN_TYPE: 3260db6ed55dSShreyas NC mod->output_pin_type = tkn_elem->value; 3261db6ed55dSShreyas NC break; 3262db6ed55dSShreyas NC 3263db6ed55dSShreyas NC case SKL_TKN_U8_IN_QUEUE_COUNT: 3264db6ed55dSShreyas NC mod->max_input_pins = tkn_elem->value; 3265db6ed55dSShreyas NC break; 3266db6ed55dSShreyas NC 3267db6ed55dSShreyas NC case SKL_TKN_U8_OUT_QUEUE_COUNT: 3268db6ed55dSShreyas NC mod->max_output_pins = tkn_elem->value; 3269db6ed55dSShreyas NC break; 3270db6ed55dSShreyas NC 3271db6ed55dSShreyas NC case SKL_TKN_MM_U8_NUM_RES: 3272db6ed55dSShreyas NC mod->nr_resources = tkn_elem->value; 3273db6ed55dSShreyas NC break; 3274db6ed55dSShreyas NC 3275db6ed55dSShreyas NC case SKL_TKN_MM_U8_NUM_INTF: 3276db6ed55dSShreyas NC mod->nr_interfaces = tkn_elem->value; 3277db6ed55dSShreyas NC break; 3278db6ed55dSShreyas NC 3279db6ed55dSShreyas NC default: 3280db6ed55dSShreyas NC dev_err(dev, "Invalid mod info token %d", tkn_elem->token); 3281db6ed55dSShreyas NC return -EINVAL; 3282db6ed55dSShreyas NC } 3283db6ed55dSShreyas NC 3284db6ed55dSShreyas NC return 0; 3285db6ed55dSShreyas NC } 3286db6ed55dSShreyas NC 3287db6ed55dSShreyas NC 3288541070ceSShreyas NC static int skl_tplg_get_int_tkn(struct device *dev, 3289541070ceSShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem, 3290*bcc2a2dcSCezary Rojewski struct skl_dev *skl) 3291541070ceSShreyas NC { 3292d00cc2f1SGustavo A. R. Silva int tkn_count = 0, ret; 3293db6ed55dSShreyas NC static int mod_idx, res_val_idx, intf_val_idx, dir, pin_idx; 3294db6ed55dSShreyas NC struct skl_module_res *res = NULL; 3295db6ed55dSShreyas NC struct skl_module_iface *fmt = NULL; 3296db6ed55dSShreyas NC struct skl_module *mod = NULL; 329743762355SPradeep Tewani static struct skl_astate_param *astate_table; 329843762355SPradeep Tewani static int astate_cfg_idx, count; 3299db6ed55dSShreyas NC int i; 3300d00cc2f1SGustavo A. R. Silva size_t size; 3301db6ed55dSShreyas NC 3302db6ed55dSShreyas NC if (skl->modules) { 3303db6ed55dSShreyas NC mod = skl->modules[mod_idx]; 3304db6ed55dSShreyas NC res = &mod->resources[res_val_idx]; 3305db6ed55dSShreyas NC fmt = &mod->formats[intf_val_idx]; 3306db6ed55dSShreyas NC } 3307541070ceSShreyas NC 3308541070ceSShreyas NC switch (tkn_elem->token) { 3309541070ceSShreyas NC case SKL_TKN_U32_LIB_COUNT: 3310*bcc2a2dcSCezary Rojewski skl->lib_count = tkn_elem->value; 3311db6ed55dSShreyas NC break; 3312db6ed55dSShreyas NC 3313db6ed55dSShreyas NC case SKL_TKN_U8_NUM_MOD: 3314db6ed55dSShreyas NC skl->nr_modules = tkn_elem->value; 3315db6ed55dSShreyas NC skl->modules = devm_kcalloc(dev, skl->nr_modules, 3316db6ed55dSShreyas NC sizeof(*skl->modules), GFP_KERNEL); 3317db6ed55dSShreyas NC if (!skl->modules) 3318db6ed55dSShreyas NC return -ENOMEM; 3319db6ed55dSShreyas NC 3320db6ed55dSShreyas NC for (i = 0; i < skl->nr_modules; i++) { 3321db6ed55dSShreyas NC skl->modules[i] = devm_kzalloc(dev, 3322db6ed55dSShreyas NC sizeof(struct skl_module), GFP_KERNEL); 3323db6ed55dSShreyas NC if (!skl->modules[i]) 3324db6ed55dSShreyas NC return -ENOMEM; 3325db6ed55dSShreyas NC } 3326db6ed55dSShreyas NC break; 3327db6ed55dSShreyas NC 3328db6ed55dSShreyas NC case SKL_TKN_MM_U8_MOD_IDX: 3329db6ed55dSShreyas NC mod_idx = tkn_elem->value; 3330db6ed55dSShreyas NC break; 3331db6ed55dSShreyas NC 333243762355SPradeep Tewani case SKL_TKN_U32_ASTATE_COUNT: 333343762355SPradeep Tewani if (astate_table != NULL) { 333443762355SPradeep Tewani dev_err(dev, "More than one entry for A-State count"); 333543762355SPradeep Tewani return -EINVAL; 333643762355SPradeep Tewani } 333743762355SPradeep Tewani 333843762355SPradeep Tewani if (tkn_elem->value > SKL_MAX_ASTATE_CFG) { 333943762355SPradeep Tewani dev_err(dev, "Invalid A-State count %d\n", 334043762355SPradeep Tewani tkn_elem->value); 334143762355SPradeep Tewani return -EINVAL; 334243762355SPradeep Tewani } 334343762355SPradeep Tewani 3344d00cc2f1SGustavo A. R. Silva size = struct_size(skl->cfg.astate_cfg, astate_table, 3345d00cc2f1SGustavo A. R. Silva tkn_elem->value); 334643762355SPradeep Tewani skl->cfg.astate_cfg = devm_kzalloc(dev, size, GFP_KERNEL); 334743762355SPradeep Tewani if (!skl->cfg.astate_cfg) 334843762355SPradeep Tewani return -ENOMEM; 334943762355SPradeep Tewani 335043762355SPradeep Tewani astate_table = skl->cfg.astate_cfg->astate_table; 335143762355SPradeep Tewani count = skl->cfg.astate_cfg->count = tkn_elem->value; 335243762355SPradeep Tewani break; 335343762355SPradeep Tewani 335443762355SPradeep Tewani case SKL_TKN_U32_ASTATE_IDX: 335543762355SPradeep Tewani if (tkn_elem->value >= count) { 335643762355SPradeep Tewani dev_err(dev, "Invalid A-State index %d\n", 335743762355SPradeep Tewani tkn_elem->value); 335843762355SPradeep Tewani return -EINVAL; 335943762355SPradeep Tewani } 336043762355SPradeep Tewani 336143762355SPradeep Tewani astate_cfg_idx = tkn_elem->value; 336243762355SPradeep Tewani break; 336343762355SPradeep Tewani 336443762355SPradeep Tewani case SKL_TKN_U32_ASTATE_KCPS: 336543762355SPradeep Tewani astate_table[astate_cfg_idx].kcps = tkn_elem->value; 336643762355SPradeep Tewani break; 336743762355SPradeep Tewani 336843762355SPradeep Tewani case SKL_TKN_U32_ASTATE_CLK_SRC: 336943762355SPradeep Tewani astate_table[astate_cfg_idx].clk_src = tkn_elem->value; 337043762355SPradeep Tewani break; 337143762355SPradeep Tewani 3372db6ed55dSShreyas NC case SKL_TKN_U8_IN_PIN_TYPE: 3373db6ed55dSShreyas NC case SKL_TKN_U8_OUT_PIN_TYPE: 3374db6ed55dSShreyas NC case SKL_TKN_U8_IN_QUEUE_COUNT: 3375db6ed55dSShreyas NC case SKL_TKN_U8_OUT_QUEUE_COUNT: 3376db6ed55dSShreyas NC case SKL_TKN_MM_U8_NUM_RES: 3377db6ed55dSShreyas NC case SKL_TKN_MM_U8_NUM_INTF: 3378db6ed55dSShreyas NC ret = skl_tplg_fill_mod_info(dev, tkn_elem, mod); 3379db6ed55dSShreyas NC if (ret < 0) 3380db6ed55dSShreyas NC return ret; 3381db6ed55dSShreyas NC break; 3382db6ed55dSShreyas NC 3383db6ed55dSShreyas NC case SKL_TKN_U32_DIR_PIN_COUNT: 3384db6ed55dSShreyas NC dir = tkn_elem->value & SKL_IN_DIR_BIT_MASK; 3385db6ed55dSShreyas NC pin_idx = (tkn_elem->value & SKL_PIN_COUNT_MASK) >> 4; 3386db6ed55dSShreyas NC break; 3387db6ed55dSShreyas NC 3388db6ed55dSShreyas NC case SKL_TKN_MM_U32_RES_ID: 3389db6ed55dSShreyas NC if (!res) 3390db6ed55dSShreyas NC return -EINVAL; 3391db6ed55dSShreyas NC 3392db6ed55dSShreyas NC res->id = tkn_elem->value; 3393db6ed55dSShreyas NC res_val_idx = tkn_elem->value; 3394db6ed55dSShreyas NC break; 3395db6ed55dSShreyas NC 3396db6ed55dSShreyas NC case SKL_TKN_MM_U32_FMT_ID: 3397db6ed55dSShreyas NC if (!fmt) 3398db6ed55dSShreyas NC return -EINVAL; 3399db6ed55dSShreyas NC 3400db6ed55dSShreyas NC fmt->fmt_idx = tkn_elem->value; 3401db6ed55dSShreyas NC intf_val_idx = tkn_elem->value; 3402db6ed55dSShreyas NC break; 3403db6ed55dSShreyas NC 3404db6ed55dSShreyas NC case SKL_TKN_MM_U32_CPS: 3405db6ed55dSShreyas NC case SKL_TKN_MM_U32_DMA_SIZE: 3406db6ed55dSShreyas NC case SKL_TKN_MM_U32_CPC: 3407db6ed55dSShreyas NC case SKL_TKN_U32_MEM_PAGES: 3408db6ed55dSShreyas NC case SKL_TKN_U32_OBS: 3409db6ed55dSShreyas NC case SKL_TKN_U32_IBS: 3410db6ed55dSShreyas NC case SKL_TKN_MM_U32_RES_PIN_ID: 3411db6ed55dSShreyas NC case SKL_TKN_MM_U32_PIN_BUF: 3412db6ed55dSShreyas NC ret = skl_tplg_fill_res_tkn(dev, tkn_elem, res, pin_idx, dir); 3413db6ed55dSShreyas NC if (ret < 0) 3414db6ed55dSShreyas NC return ret; 3415db6ed55dSShreyas NC 3416db6ed55dSShreyas NC break; 3417db6ed55dSShreyas NC 3418db6ed55dSShreyas NC case SKL_TKN_MM_U32_NUM_IN_FMT: 3419db6ed55dSShreyas NC if (!fmt) 3420db6ed55dSShreyas NC return -EINVAL; 3421db6ed55dSShreyas NC 3422db6ed55dSShreyas NC res->nr_input_pins = tkn_elem->value; 3423db6ed55dSShreyas NC break; 3424db6ed55dSShreyas NC 3425db6ed55dSShreyas NC case SKL_TKN_MM_U32_NUM_OUT_FMT: 3426db6ed55dSShreyas NC if (!fmt) 3427db6ed55dSShreyas NC return -EINVAL; 3428db6ed55dSShreyas NC 3429db6ed55dSShreyas NC res->nr_output_pins = tkn_elem->value; 3430db6ed55dSShreyas NC break; 3431db6ed55dSShreyas NC 3432db6ed55dSShreyas NC case SKL_TKN_U32_FMT_CH: 3433db6ed55dSShreyas NC case SKL_TKN_U32_FMT_FREQ: 3434db6ed55dSShreyas NC case SKL_TKN_U32_FMT_BIT_DEPTH: 3435db6ed55dSShreyas NC case SKL_TKN_U32_FMT_SAMPLE_SIZE: 3436db6ed55dSShreyas NC case SKL_TKN_U32_FMT_CH_CONFIG: 3437db6ed55dSShreyas NC case SKL_TKN_U32_FMT_INTERLEAVE: 3438db6ed55dSShreyas NC case SKL_TKN_U32_FMT_SAMPLE_TYPE: 3439db6ed55dSShreyas NC case SKL_TKN_U32_FMT_CH_MAP: 3440db6ed55dSShreyas NC case SKL_TKN_MM_U32_INTF_PIN_ID: 3441db6ed55dSShreyas NC ret = skl_tplg_manifest_fill_fmt(dev, fmt, tkn_elem, 3442db6ed55dSShreyas NC dir, pin_idx); 3443db6ed55dSShreyas NC if (ret < 0) 3444db6ed55dSShreyas NC return ret; 3445541070ceSShreyas NC break; 3446541070ceSShreyas NC 3447541070ceSShreyas NC default: 3448ecd286a9SColin Ian King dev_err(dev, "Not a manifest token %d\n", tkn_elem->token); 3449541070ceSShreyas NC return -EINVAL; 3450541070ceSShreyas NC } 3451db6ed55dSShreyas NC tkn_count++; 3452541070ceSShreyas NC 3453541070ceSShreyas NC return tkn_count; 3454541070ceSShreyas NC } 3455541070ceSShreyas NC 3456db6ed55dSShreyas NC static int skl_tplg_get_manifest_uuid(struct device *dev, 3457*bcc2a2dcSCezary Rojewski struct skl_dev *skl, 3458db6ed55dSShreyas NC struct snd_soc_tplg_vendor_uuid_elem *uuid_tkn) 3459db6ed55dSShreyas NC { 3460db6ed55dSShreyas NC static int ref_count; 3461db6ed55dSShreyas NC struct skl_module *mod; 3462db6ed55dSShreyas NC 3463db6ed55dSShreyas NC if (uuid_tkn->token == SKL_TKN_UUID) { 3464db6ed55dSShreyas NC mod = skl->modules[ref_count]; 34659e0784d0SAndy Shevchenko guid_copy(&mod->uuid, (guid_t *)&uuid_tkn->uuid); 3466db6ed55dSShreyas NC ref_count++; 3467db6ed55dSShreyas NC } else { 3468db6ed55dSShreyas NC dev_err(dev, "Not an UUID token tkn %d\n", uuid_tkn->token); 3469db6ed55dSShreyas NC return -EINVAL; 3470db6ed55dSShreyas NC } 3471db6ed55dSShreyas NC 3472db6ed55dSShreyas NC return 0; 3473db6ed55dSShreyas NC } 3474db6ed55dSShreyas NC 3475541070ceSShreyas NC /* 3476541070ceSShreyas NC * Fill the manifest structure by parsing the tokens based on the 3477541070ceSShreyas NC * type. 3478541070ceSShreyas NC */ 3479541070ceSShreyas NC static int skl_tplg_get_manifest_tkn(struct device *dev, 3480*bcc2a2dcSCezary Rojewski char *pvt_data, struct skl_dev *skl, 3481541070ceSShreyas NC int block_size) 3482541070ceSShreyas NC { 3483541070ceSShreyas NC int tkn_count = 0, ret; 3484541070ceSShreyas NC int off = 0, tuple_size = 0; 3485541070ceSShreyas NC struct snd_soc_tplg_vendor_array *array; 3486541070ceSShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem; 3487541070ceSShreyas NC 3488541070ceSShreyas NC if (block_size <= 0) 3489541070ceSShreyas NC return -EINVAL; 3490541070ceSShreyas NC 3491541070ceSShreyas NC while (tuple_size < block_size) { 3492541070ceSShreyas NC array = (struct snd_soc_tplg_vendor_array *)(pvt_data + off); 3493541070ceSShreyas NC off += array->size; 3494541070ceSShreyas NC switch (array->type) { 3495541070ceSShreyas NC case SND_SOC_TPLG_TUPLE_TYPE_STRING: 3496eee0e16fSJeeja KP ret = skl_tplg_get_str_tkn(dev, array, skl); 3497541070ceSShreyas NC 3498541070ceSShreyas NC if (ret < 0) 3499541070ceSShreyas NC return ret; 35000a716776SShreyas NC tkn_count = ret; 3501541070ceSShreyas NC 3502541070ceSShreyas NC tuple_size += tkn_count * 3503541070ceSShreyas NC sizeof(struct snd_soc_tplg_vendor_string_elem); 3504541070ceSShreyas NC continue; 3505541070ceSShreyas NC 3506541070ceSShreyas NC case SND_SOC_TPLG_TUPLE_TYPE_UUID: 3507db6ed55dSShreyas NC ret = skl_tplg_get_manifest_uuid(dev, skl, array->uuid); 3508db6ed55dSShreyas NC if (ret < 0) 3509db6ed55dSShreyas NC return ret; 3510db6ed55dSShreyas NC 3511db6ed55dSShreyas NC tuple_size += sizeof(*array->uuid); 3512541070ceSShreyas NC continue; 3513541070ceSShreyas NC 3514541070ceSShreyas NC default: 3515541070ceSShreyas NC tkn_elem = array->value; 3516541070ceSShreyas NC tkn_count = 0; 3517541070ceSShreyas NC break; 3518541070ceSShreyas NC } 3519541070ceSShreyas NC 3520541070ceSShreyas NC while (tkn_count <= array->num_elems - 1) { 3521541070ceSShreyas NC ret = skl_tplg_get_int_tkn(dev, 3522eee0e16fSJeeja KP tkn_elem, skl); 3523541070ceSShreyas NC if (ret < 0) 3524541070ceSShreyas NC return ret; 3525541070ceSShreyas NC 3526541070ceSShreyas NC tkn_count = tkn_count + ret; 3527541070ceSShreyas NC tkn_elem++; 3528541070ceSShreyas NC } 35299fc129f6SShreyas NC tuple_size += (tkn_count * sizeof(*tkn_elem)); 3530541070ceSShreyas NC tkn_count = 0; 3531541070ceSShreyas NC } 3532541070ceSShreyas NC 35339fc129f6SShreyas NC return off; 3534541070ceSShreyas NC } 3535541070ceSShreyas NC 3536541070ceSShreyas NC /* 3537541070ceSShreyas NC * Parse manifest private data for tokens. The private data block is 3538541070ceSShreyas NC * preceded by descriptors for type and size of data block. 3539541070ceSShreyas NC */ 3540541070ceSShreyas NC static int skl_tplg_get_manifest_data(struct snd_soc_tplg_manifest *manifest, 3541*bcc2a2dcSCezary Rojewski struct device *dev, struct skl_dev *skl) 3542541070ceSShreyas NC { 3543541070ceSShreyas NC struct snd_soc_tplg_vendor_array *array; 3544541070ceSShreyas NC int num_blocks, block_size = 0, block_type, off = 0; 3545541070ceSShreyas NC char *data; 3546541070ceSShreyas NC int ret; 3547541070ceSShreyas NC 3548541070ceSShreyas NC /* Read the NUM_DATA_BLOCKS descriptor */ 3549541070ceSShreyas NC array = (struct snd_soc_tplg_vendor_array *)manifest->priv.data; 3550541070ceSShreyas NC ret = skl_tplg_get_desc_blocks(dev, array); 3551541070ceSShreyas NC if (ret < 0) 3552541070ceSShreyas NC return ret; 3553541070ceSShreyas NC num_blocks = ret; 3554541070ceSShreyas NC 3555541070ceSShreyas NC off += array->size; 3556541070ceSShreyas NC /* Read the BLOCK_TYPE and BLOCK_SIZE descriptor */ 3557541070ceSShreyas NC while (num_blocks > 0) { 35589fc129f6SShreyas NC array = (struct snd_soc_tplg_vendor_array *) 35599fc129f6SShreyas NC (manifest->priv.data + off); 3560541070ceSShreyas NC ret = skl_tplg_get_desc_blocks(dev, array); 3561541070ceSShreyas NC 3562541070ceSShreyas NC if (ret < 0) 3563541070ceSShreyas NC return ret; 3564541070ceSShreyas NC block_type = ret; 3565541070ceSShreyas NC off += array->size; 3566541070ceSShreyas NC 3567541070ceSShreyas NC array = (struct snd_soc_tplg_vendor_array *) 3568541070ceSShreyas NC (manifest->priv.data + off); 3569541070ceSShreyas NC 3570541070ceSShreyas NC ret = skl_tplg_get_desc_blocks(dev, array); 3571541070ceSShreyas NC 3572541070ceSShreyas NC if (ret < 0) 3573541070ceSShreyas NC return ret; 3574541070ceSShreyas NC block_size = ret; 3575541070ceSShreyas NC off += array->size; 3576541070ceSShreyas NC 3577541070ceSShreyas NC array = (struct snd_soc_tplg_vendor_array *) 3578541070ceSShreyas NC (manifest->priv.data + off); 3579541070ceSShreyas NC 3580541070ceSShreyas NC data = (manifest->priv.data + off); 3581541070ceSShreyas NC 3582541070ceSShreyas NC if (block_type == SKL_TYPE_TUPLE) { 3583eee0e16fSJeeja KP ret = skl_tplg_get_manifest_tkn(dev, data, skl, 3584541070ceSShreyas NC block_size); 3585541070ceSShreyas NC 3586541070ceSShreyas NC if (ret < 0) 3587541070ceSShreyas NC return ret; 3588541070ceSShreyas NC 3589541070ceSShreyas NC --num_blocks; 3590541070ceSShreyas NC } else { 3591541070ceSShreyas NC return -EINVAL; 3592541070ceSShreyas NC } 35939fc129f6SShreyas NC off += ret; 3594541070ceSShreyas NC } 3595541070ceSShreyas NC 3596541070ceSShreyas NC return 0; 3597541070ceSShreyas NC } 3598541070ceSShreyas NC 3599c60b613aSLiam Girdwood static int skl_manifest_load(struct snd_soc_component *cmpnt, int index, 360015ecaba9SKranthi G struct snd_soc_tplg_manifest *manifest) 360115ecaba9SKranthi G { 360276f56faeSRakesh Ughreja struct hdac_bus *bus = snd_soc_component_get_drvdata(cmpnt); 3603*bcc2a2dcSCezary Rojewski struct skl_dev *skl = bus_to_skl(bus); 360415ecaba9SKranthi G 3605c15ad605SVinod Koul /* proceed only if we have private data defined */ 3606c15ad605SVinod Koul if (manifest->priv.size == 0) 3607c15ad605SVinod Koul return 0; 3608c15ad605SVinod Koul 3609eee0e16fSJeeja KP skl_tplg_get_manifest_data(manifest, bus->dev, skl); 3610541070ceSShreyas NC 3611*bcc2a2dcSCezary Rojewski if (skl->lib_count > SKL_MAX_LIB) { 361215ecaba9SKranthi G dev_err(bus->dev, "Exceeding max Library count. Got:%d\n", 3613*bcc2a2dcSCezary Rojewski skl->lib_count); 3614eee0e16fSJeeja KP return -EINVAL; 361515ecaba9SKranthi G } 361615ecaba9SKranthi G 3617eee0e16fSJeeja KP return 0; 361815ecaba9SKranthi G } 361915ecaba9SKranthi G 36203af36706SVinod Koul static struct snd_soc_tplg_ops skl_tplg_ops = { 36213af36706SVinod Koul .widget_load = skl_tplg_widget_load, 3622140adfbaSJeeja KP .control_load = skl_tplg_control_load, 3623140adfbaSJeeja KP .bytes_ext_ops = skl_tlv_ops, 3624140adfbaSJeeja KP .bytes_ext_ops_count = ARRAY_SIZE(skl_tlv_ops), 36257a1b749bSDharageswari R .io_ops = skl_tplg_kcontrol_ops, 36267a1b749bSDharageswari R .io_ops_count = ARRAY_SIZE(skl_tplg_kcontrol_ops), 362715ecaba9SKranthi G .manifest = skl_manifest_load, 3628606e21fdSGuneshwor Singh .dai_load = skl_dai_load, 36293af36706SVinod Koul }; 36303af36706SVinod Koul 3631287af4f9SJeeja KP /* 3632287af4f9SJeeja KP * A pipe can have multiple modules, each of them will be a DAPM widget as 3633287af4f9SJeeja KP * well. While managing a pipeline we need to get the list of all the 3634287af4f9SJeeja KP * widgets in a pipelines, so this helper - skl_tplg_create_pipe_widget_list() 3635287af4f9SJeeja KP * helps to get the SKL type widgets in that pipeline 3636287af4f9SJeeja KP */ 363756b03b4cSKuninori Morimoto static int skl_tplg_create_pipe_widget_list(struct snd_soc_component *component) 3638287af4f9SJeeja KP { 3639287af4f9SJeeja KP struct snd_soc_dapm_widget *w; 3640287af4f9SJeeja KP struct skl_module_cfg *mcfg = NULL; 3641287af4f9SJeeja KP struct skl_pipe_module *p_module = NULL; 3642287af4f9SJeeja KP struct skl_pipe *pipe; 3643287af4f9SJeeja KP 364456b03b4cSKuninori Morimoto list_for_each_entry(w, &component->card->widgets, list) { 3645a1f362d8SMark Brown if (is_skl_dsp_widget_type(w, component->dev) && w->priv) { 3646287af4f9SJeeja KP mcfg = w->priv; 3647287af4f9SJeeja KP pipe = mcfg->pipe; 3648287af4f9SJeeja KP 364956b03b4cSKuninori Morimoto p_module = devm_kzalloc(component->dev, 3650287af4f9SJeeja KP sizeof(*p_module), GFP_KERNEL); 3651287af4f9SJeeja KP if (!p_module) 3652287af4f9SJeeja KP return -ENOMEM; 3653287af4f9SJeeja KP 3654287af4f9SJeeja KP p_module->w = w; 3655287af4f9SJeeja KP list_add_tail(&p_module->node, &pipe->w_list); 3656287af4f9SJeeja KP } 3657287af4f9SJeeja KP } 3658287af4f9SJeeja KP 3659287af4f9SJeeja KP return 0; 3660287af4f9SJeeja KP } 3661287af4f9SJeeja KP 3662*bcc2a2dcSCezary Rojewski static void skl_tplg_set_pipe_type(struct skl_dev *skl, struct skl_pipe *pipe) 3663f0aa94faSJeeja KP { 3664f0aa94faSJeeja KP struct skl_pipe_module *w_module; 3665f0aa94faSJeeja KP struct snd_soc_dapm_widget *w; 3666f0aa94faSJeeja KP struct skl_module_cfg *mconfig; 3667f0aa94faSJeeja KP bool host_found = false, link_found = false; 3668f0aa94faSJeeja KP 3669f0aa94faSJeeja KP list_for_each_entry(w_module, &pipe->w_list, node) { 3670f0aa94faSJeeja KP w = w_module->w; 3671f0aa94faSJeeja KP mconfig = w->priv; 3672f0aa94faSJeeja KP 3673f0aa94faSJeeja KP if (mconfig->dev_type == SKL_DEVICE_HDAHOST) 3674f0aa94faSJeeja KP host_found = true; 3675f0aa94faSJeeja KP else if (mconfig->dev_type != SKL_DEVICE_NONE) 3676f0aa94faSJeeja KP link_found = true; 3677f0aa94faSJeeja KP } 3678f0aa94faSJeeja KP 3679f0aa94faSJeeja KP if (host_found && link_found) 3680f0aa94faSJeeja KP pipe->passthru = true; 3681f0aa94faSJeeja KP else 3682f0aa94faSJeeja KP pipe->passthru = false; 3683f0aa94faSJeeja KP } 3684f0aa94faSJeeja KP 36853af36706SVinod Koul /* This will be read from topology manifest, currently defined here */ 36863af36706SVinod Koul #define SKL_MAX_MCPS 30000000 36873af36706SVinod Koul #define SKL_FW_MAX_MEM 1000000 36883af36706SVinod Koul 36893af36706SVinod Koul /* 36903af36706SVinod Koul * SKL topology init routine 36913af36706SVinod Koul */ 369276f56faeSRakesh Ughreja int skl_tplg_init(struct snd_soc_component *component, struct hdac_bus *bus) 36933af36706SVinod Koul { 36943af36706SVinod Koul int ret; 36953af36706SVinod Koul const struct firmware *fw; 3696*bcc2a2dcSCezary Rojewski struct skl_dev *skl = bus_to_skl(bus); 3697f0aa94faSJeeja KP struct skl_pipeline *ppl; 36983af36706SVinod Koul 36994b235c43SVinod Koul ret = request_firmware(&fw, skl->tplg_name, bus->dev); 37003af36706SVinod Koul if (ret < 0) { 370119de7179SChintan Patel dev_info(bus->dev, "tplg fw %s load failed with %d, falling back to dfw_sst.bin", 37024b235c43SVinod Koul skl->tplg_name, ret); 37034b235c43SVinod Koul ret = request_firmware(&fw, "dfw_sst.bin", bus->dev); 37044b235c43SVinod Koul if (ret < 0) { 37054b235c43SVinod Koul dev_err(bus->dev, "Fallback tplg fw %s load failed with %d\n", 37063af36706SVinod Koul "dfw_sst.bin", ret); 37073af36706SVinod Koul return ret; 37083af36706SVinod Koul } 37094b235c43SVinod Koul } 37103af36706SVinod Koul 37113af36706SVinod Koul /* 37123af36706SVinod Koul * The complete tplg for SKL is loaded as index 0, we don't use 37133af36706SVinod Koul * any other index 37143af36706SVinod Koul */ 371556b03b4cSKuninori Morimoto ret = snd_soc_tplg_component_load(component, 3716b663a8c5SJeeja KP &skl_tplg_ops, fw, 0); 37173af36706SVinod Koul if (ret < 0) { 37183af36706SVinod Koul dev_err(bus->dev, "tplg component load failed%d\n", ret); 3719c14a82c7SSudip Mukherjee release_firmware(fw); 37203af36706SVinod Koul return -EINVAL; 37213af36706SVinod Koul } 37223af36706SVinod Koul 37233af36706SVinod Koul skl->resource.max_mcps = SKL_MAX_MCPS; 37243af36706SVinod Koul skl->resource.max_mem = SKL_FW_MAX_MEM; 37253af36706SVinod Koul 3726d8018361SVinod Koul skl->tplg = fw; 372756b03b4cSKuninori Morimoto ret = skl_tplg_create_pipe_widget_list(component); 3728287af4f9SJeeja KP if (ret < 0) 3729287af4f9SJeeja KP return ret; 3730d8018361SVinod Koul 3731f0aa94faSJeeja KP list_for_each_entry(ppl, &skl->ppl_list, node) 3732f0aa94faSJeeja KP skl_tplg_set_pipe_type(skl, ppl->pipe); 37333af36706SVinod Koul 37343af36706SVinod Koul return 0; 3735e4e2d2f4SJeeja KP } 3736e79986ceSAmadeusz Sławiński 3737e79986ceSAmadeusz Sławiński void skl_tplg_exit(struct snd_soc_component *component, struct hdac_bus *bus) 3738e79986ceSAmadeusz Sławiński { 3739*bcc2a2dcSCezary Rojewski struct skl_dev *skl = bus_to_skl(bus); 3740e79986ceSAmadeusz Sławiński struct skl_pipeline *ppl, *tmp; 3741e79986ceSAmadeusz Sławiński 3742e79986ceSAmadeusz Sławiński if (!list_empty(&skl->ppl_list)) 3743e79986ceSAmadeusz Sławiński list_for_each_entry_safe(ppl, tmp, &skl->ppl_list, node) 3744e79986ceSAmadeusz Sławiński list_del(&ppl->node); 3745e79986ceSAmadeusz Sławiński 3746e79986ceSAmadeusz Sławiński /* clean up topology */ 3747e79986ceSAmadeusz Sławiński snd_soc_tplg_component_remove(component, SND_SOC_TPLG_INDEX_ALL); 3748e79986ceSAmadeusz Sławiński 3749e79986ceSAmadeusz Sławiński release_firmware(skl->tplg); 3750e79986ceSAmadeusz Sławiński } 3751