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> 1563643b59SPierre-Louis Bossart #include <sound/intel-nhlt.h> 16e4e2d2f4SJeeja KP #include <sound/soc.h> 17e4e2d2f4SJeeja KP #include <sound/soc-topology.h> 186277e832SShreyas NC #include <uapi/sound/snd_sst_tokens.h> 190c24fdc0SGuenter Roeck #include <uapi/sound/skl-tplg-interface.h> 20e4e2d2f4SJeeja KP #include "skl-sst-dsp.h" 21e4e2d2f4SJeeja KP #include "skl-sst-ipc.h" 22e4e2d2f4SJeeja KP #include "skl-topology.h" 23e4e2d2f4SJeeja KP #include "skl.h" 246c5768b3SDharageswari R #include "../common/sst-dsp.h" 256c5768b3SDharageswari R #include "../common/sst-dsp-priv.h" 26e4e2d2f4SJeeja KP 27f7590d4fSJeeja KP #define SKL_CH_FIXUP_MASK (1 << 0) 28f7590d4fSJeeja KP #define SKL_RATE_FIXUP_MASK (1 << 1) 29f7590d4fSJeeja KP #define SKL_FMT_FIXUP_MASK (1 << 2) 306277e832SShreyas NC #define SKL_IN_DIR_BIT_MASK BIT(0) 316277e832SShreyas NC #define SKL_PIN_COUNT_MASK GENMASK(7, 4) 32f7590d4fSJeeja KP 337a1b749bSDharageswari R static const int mic_mono_list[] = { 347a1b749bSDharageswari R 0, 1, 2, 3, 357a1b749bSDharageswari R }; 367a1b749bSDharageswari R static const int mic_stereo_list[][SKL_CH_STEREO] = { 377a1b749bSDharageswari R {0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}, 387a1b749bSDharageswari R }; 397a1b749bSDharageswari R static const int mic_trio_list[][SKL_CH_TRIO] = { 407a1b749bSDharageswari R {0, 1, 2}, {0, 1, 3}, {0, 2, 3}, {1, 2, 3}, 417a1b749bSDharageswari R }; 427a1b749bSDharageswari R static const int mic_quatro_list[][SKL_CH_QUATRO] = { 437a1b749bSDharageswari R {0, 1, 2, 3}, 447a1b749bSDharageswari R }; 457a1b749bSDharageswari R 46f6fa56e2SRamesh Babu #define CHECK_HW_PARAMS(ch, freq, bps, prm_ch, prm_freq, prm_bps) \ 47f6fa56e2SRamesh Babu ((ch == prm_ch) && (bps == prm_bps) && (freq == prm_freq)) 48f6fa56e2SRamesh Babu 49bcc2a2dcSCezary Rojewski void skl_tplg_d0i3_get(struct skl_dev *skl, enum d0i3_capability caps) 50a83e3b4cSVinod Koul { 51bcc2a2dcSCezary Rojewski struct skl_d0i3_data *d0i3 = &skl->d0i3; 52a83e3b4cSVinod Koul 53a83e3b4cSVinod Koul switch (caps) { 54a83e3b4cSVinod Koul case SKL_D0I3_NONE: 55a83e3b4cSVinod Koul d0i3->non_d0i3++; 56a83e3b4cSVinod Koul break; 57a83e3b4cSVinod Koul 58a83e3b4cSVinod Koul case SKL_D0I3_STREAMING: 59a83e3b4cSVinod Koul d0i3->streaming++; 60a83e3b4cSVinod Koul break; 61a83e3b4cSVinod Koul 62a83e3b4cSVinod Koul case SKL_D0I3_NON_STREAMING: 63a83e3b4cSVinod Koul d0i3->non_streaming++; 64a83e3b4cSVinod Koul break; 65a83e3b4cSVinod Koul } 66a83e3b4cSVinod Koul } 67a83e3b4cSVinod Koul 68bcc2a2dcSCezary Rojewski void skl_tplg_d0i3_put(struct skl_dev *skl, enum d0i3_capability caps) 69a83e3b4cSVinod Koul { 70bcc2a2dcSCezary Rojewski struct skl_d0i3_data *d0i3 = &skl->d0i3; 71a83e3b4cSVinod Koul 72a83e3b4cSVinod Koul switch (caps) { 73a83e3b4cSVinod Koul case SKL_D0I3_NONE: 74a83e3b4cSVinod Koul d0i3->non_d0i3--; 75a83e3b4cSVinod Koul break; 76a83e3b4cSVinod Koul 77a83e3b4cSVinod Koul case SKL_D0I3_STREAMING: 78a83e3b4cSVinod Koul d0i3->streaming--; 79a83e3b4cSVinod Koul break; 80a83e3b4cSVinod Koul 81a83e3b4cSVinod Koul case SKL_D0I3_NON_STREAMING: 82a83e3b4cSVinod Koul d0i3->non_streaming--; 83a83e3b4cSVinod Koul break; 84a83e3b4cSVinod Koul } 85a83e3b4cSVinod Koul } 86a83e3b4cSVinod Koul 87e4e2d2f4SJeeja KP /* 88e4e2d2f4SJeeja KP * SKL DSP driver modelling uses only few DAPM widgets so for rest we will 89e4e2d2f4SJeeja KP * ignore. This helpers checks if the SKL driver handles this widget type 90e4e2d2f4SJeeja KP */ 91cb1f904dSGuneshwor Singh static int is_skl_dsp_widget_type(struct snd_soc_dapm_widget *w, 92cb1f904dSGuneshwor Singh struct device *dev) 93e4e2d2f4SJeeja KP { 94cb1f904dSGuneshwor Singh if (w->dapm->dev != dev) 95cb1f904dSGuneshwor Singh return false; 96cb1f904dSGuneshwor Singh 97e4e2d2f4SJeeja KP switch (w->id) { 98e4e2d2f4SJeeja KP case snd_soc_dapm_dai_link: 99e4e2d2f4SJeeja KP case snd_soc_dapm_dai_in: 100e4e2d2f4SJeeja KP case snd_soc_dapm_aif_in: 101e4e2d2f4SJeeja KP case snd_soc_dapm_aif_out: 102e4e2d2f4SJeeja KP case snd_soc_dapm_dai_out: 103e4e2d2f4SJeeja KP case snd_soc_dapm_switch: 104fe65324eSRakesh Ughreja case snd_soc_dapm_output: 105fe65324eSRakesh Ughreja case snd_soc_dapm_mux: 106fe65324eSRakesh Ughreja 107e4e2d2f4SJeeja KP return false; 108e4e2d2f4SJeeja KP default: 109e4e2d2f4SJeeja KP return true; 110e4e2d2f4SJeeja KP } 111e4e2d2f4SJeeja KP } 112e4e2d2f4SJeeja KP 113bcc2a2dcSCezary Rojewski static void skl_dump_mconfig(struct skl_dev *skl, struct skl_module_cfg *mcfg) 114f7590d4fSJeeja KP { 115f6fa56e2SRamesh Babu struct skl_module_iface *iface = &mcfg->module->formats[0]; 116f6fa56e2SRamesh Babu 117bcc2a2dcSCezary Rojewski dev_dbg(skl->dev, "Dumping config\n"); 118bcc2a2dcSCezary Rojewski dev_dbg(skl->dev, "Input Format:\n"); 119bcc2a2dcSCezary Rojewski dev_dbg(skl->dev, "channels = %d\n", iface->inputs[0].fmt.channels); 120bcc2a2dcSCezary Rojewski dev_dbg(skl->dev, "s_freq = %d\n", iface->inputs[0].fmt.s_freq); 121bcc2a2dcSCezary Rojewski dev_dbg(skl->dev, "ch_cfg = %d\n", iface->inputs[0].fmt.ch_cfg); 122bcc2a2dcSCezary Rojewski dev_dbg(skl->dev, "valid bit depth = %d\n", 123f6fa56e2SRamesh Babu iface->inputs[0].fmt.valid_bit_depth); 124bcc2a2dcSCezary Rojewski dev_dbg(skl->dev, "Output Format:\n"); 125bcc2a2dcSCezary Rojewski dev_dbg(skl->dev, "channels = %d\n", iface->outputs[0].fmt.channels); 126bcc2a2dcSCezary Rojewski dev_dbg(skl->dev, "s_freq = %d\n", iface->outputs[0].fmt.s_freq); 127bcc2a2dcSCezary Rojewski dev_dbg(skl->dev, "valid bit depth = %d\n", 128f6fa56e2SRamesh Babu iface->outputs[0].fmt.valid_bit_depth); 129bcc2a2dcSCezary Rojewski dev_dbg(skl->dev, "ch_cfg = %d\n", iface->outputs[0].fmt.ch_cfg); 130f7590d4fSJeeja KP } 131f7590d4fSJeeja KP 132ea5a137dSSubhransu S. Prusty static void skl_tplg_update_chmap(struct skl_module_fmt *fmt, int chs) 133ea5a137dSSubhransu S. Prusty { 134ea5a137dSSubhransu S. Prusty int slot_map = 0xFFFFFFFF; 135ea5a137dSSubhransu S. Prusty int start_slot = 0; 136ea5a137dSSubhransu S. Prusty int i; 137ea5a137dSSubhransu S. Prusty 138ea5a137dSSubhransu S. Prusty for (i = 0; i < chs; i++) { 139ea5a137dSSubhransu S. Prusty /* 140ea5a137dSSubhransu S. Prusty * For 2 channels with starting slot as 0, slot map will 141ea5a137dSSubhransu S. Prusty * look like 0xFFFFFF10. 142ea5a137dSSubhransu S. Prusty */ 143ea5a137dSSubhransu S. Prusty slot_map &= (~(0xF << (4 * i)) | (start_slot << (4 * i))); 144ea5a137dSSubhransu S. Prusty start_slot++; 145ea5a137dSSubhransu S. Prusty } 146ea5a137dSSubhransu S. Prusty fmt->ch_map = slot_map; 147ea5a137dSSubhransu S. Prusty } 148ea5a137dSSubhransu S. Prusty 149f7590d4fSJeeja KP static void skl_tplg_update_params(struct skl_module_fmt *fmt, 150f7590d4fSJeeja KP struct skl_pipe_params *params, int fixup) 151f7590d4fSJeeja KP { 152f7590d4fSJeeja KP if (fixup & SKL_RATE_FIXUP_MASK) 153f7590d4fSJeeja KP fmt->s_freq = params->s_freq; 154ea5a137dSSubhransu S. Prusty if (fixup & SKL_CH_FIXUP_MASK) { 155f7590d4fSJeeja KP fmt->channels = params->ch; 156ea5a137dSSubhransu S. Prusty skl_tplg_update_chmap(fmt, fmt->channels); 157ea5a137dSSubhransu S. Prusty } 15898256f83SJeeja KP if (fixup & SKL_FMT_FIXUP_MASK) { 15998256f83SJeeja KP fmt->valid_bit_depth = skl_get_bit_depth(params->s_fmt); 16098256f83SJeeja KP 16198256f83SJeeja KP /* 16298256f83SJeeja KP * 16 bit is 16 bit container whereas 24 bit is in 32 bit 16398256f83SJeeja KP * container so update bit depth accordingly 16498256f83SJeeja KP */ 16598256f83SJeeja KP switch (fmt->valid_bit_depth) { 16698256f83SJeeja KP case SKL_DEPTH_16BIT: 16798256f83SJeeja KP fmt->bit_depth = fmt->valid_bit_depth; 16898256f83SJeeja KP break; 16998256f83SJeeja KP 17098256f83SJeeja KP default: 17198256f83SJeeja KP fmt->bit_depth = SKL_DEPTH_32BIT; 17298256f83SJeeja KP break; 17398256f83SJeeja KP } 17498256f83SJeeja KP } 17598256f83SJeeja KP 176f7590d4fSJeeja KP } 177f7590d4fSJeeja KP 178f7590d4fSJeeja KP /* 179f7590d4fSJeeja KP * A pipeline may have modules which impact the pcm parameters, like SRC, 180f7590d4fSJeeja KP * channel converter, format converter. 181f7590d4fSJeeja KP * We need to calculate the output params by applying the 'fixup' 182f7590d4fSJeeja KP * Topology will tell driver which type of fixup is to be applied by 183f7590d4fSJeeja KP * supplying the fixup mask, so based on that we calculate the output 184f7590d4fSJeeja KP * 185f7590d4fSJeeja KP * Now In FE the pcm hw_params is source/target format. Same is applicable 186f7590d4fSJeeja KP * for BE with its hw_params invoked. 187f7590d4fSJeeja KP * here based on FE, BE pipeline and direction we calculate the input and 188f7590d4fSJeeja KP * outfix and then apply that for a module 189f7590d4fSJeeja KP */ 190f7590d4fSJeeja KP static void skl_tplg_update_params_fixup(struct skl_module_cfg *m_cfg, 191f7590d4fSJeeja KP struct skl_pipe_params *params, bool is_fe) 192f7590d4fSJeeja KP { 193f7590d4fSJeeja KP int in_fixup, out_fixup; 194f7590d4fSJeeja KP struct skl_module_fmt *in_fmt, *out_fmt; 195f7590d4fSJeeja KP 1964cd9899fSHardik T Shah /* Fixups will be applied to pin 0 only */ 197f6fa56e2SRamesh Babu in_fmt = &m_cfg->module->formats[0].inputs[0].fmt; 198f6fa56e2SRamesh Babu out_fmt = &m_cfg->module->formats[0].outputs[0].fmt; 199f7590d4fSJeeja KP 200f7590d4fSJeeja KP if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) { 201f7590d4fSJeeja KP if (is_fe) { 202f7590d4fSJeeja KP in_fixup = m_cfg->params_fixup; 203f7590d4fSJeeja KP out_fixup = (~m_cfg->converter) & 204f7590d4fSJeeja KP m_cfg->params_fixup; 205f7590d4fSJeeja KP } else { 206f7590d4fSJeeja KP out_fixup = m_cfg->params_fixup; 207f7590d4fSJeeja KP in_fixup = (~m_cfg->converter) & 208f7590d4fSJeeja KP m_cfg->params_fixup; 209f7590d4fSJeeja KP } 210f7590d4fSJeeja KP } else { 211f7590d4fSJeeja KP if (is_fe) { 212f7590d4fSJeeja KP out_fixup = m_cfg->params_fixup; 213f7590d4fSJeeja KP in_fixup = (~m_cfg->converter) & 214f7590d4fSJeeja KP m_cfg->params_fixup; 215f7590d4fSJeeja KP } else { 216f7590d4fSJeeja KP in_fixup = m_cfg->params_fixup; 217f7590d4fSJeeja KP out_fixup = (~m_cfg->converter) & 218f7590d4fSJeeja KP m_cfg->params_fixup; 219f7590d4fSJeeja KP } 220f7590d4fSJeeja KP } 221f7590d4fSJeeja KP 222f7590d4fSJeeja KP skl_tplg_update_params(in_fmt, params, in_fixup); 223f7590d4fSJeeja KP skl_tplg_update_params(out_fmt, params, out_fixup); 224f7590d4fSJeeja KP } 225f7590d4fSJeeja KP 226f7590d4fSJeeja KP /* 227f7590d4fSJeeja KP * A module needs input and output buffers, which are dependent upon pcm 228f7590d4fSJeeja KP * params, so once we have calculate params, we need buffer calculation as 229f7590d4fSJeeja KP * well. 230f7590d4fSJeeja KP */ 231bcc2a2dcSCezary Rojewski static void skl_tplg_update_buffer_size(struct skl_dev *skl, 232f7590d4fSJeeja KP struct skl_module_cfg *mcfg) 233f7590d4fSJeeja KP { 234f7590d4fSJeeja KP int multiplier = 1; 2354cd9899fSHardik T Shah struct skl_module_fmt *in_fmt, *out_fmt; 236f6fa56e2SRamesh Babu struct skl_module_res *res; 2374cd9899fSHardik T Shah 2384cd9899fSHardik T Shah /* Since fixups is applied to pin 0 only, ibs, obs needs 2394cd9899fSHardik T Shah * change for pin 0 only 2404cd9899fSHardik T Shah */ 241f6fa56e2SRamesh Babu res = &mcfg->module->resources[0]; 242f6fa56e2SRamesh Babu in_fmt = &mcfg->module->formats[0].inputs[0].fmt; 243f6fa56e2SRamesh Babu out_fmt = &mcfg->module->formats[0].outputs[0].fmt; 244f7590d4fSJeeja KP 245f7590d4fSJeeja KP if (mcfg->m_type == SKL_MODULE_TYPE_SRCINT) 246f7590d4fSJeeja KP multiplier = 5; 247f0c8e1d9SSubhransu S. Prusty 248f6fa56e2SRamesh Babu res->ibs = DIV_ROUND_UP(in_fmt->s_freq, 1000) * 249998d6fb5STakashi Sakamoto in_fmt->channels * (in_fmt->bit_depth >> 3) * 250f7590d4fSJeeja KP multiplier; 251f7590d4fSJeeja KP 252f6fa56e2SRamesh Babu res->obs = DIV_ROUND_UP(out_fmt->s_freq, 1000) * 253998d6fb5STakashi Sakamoto out_fmt->channels * (out_fmt->bit_depth >> 3) * 254f7590d4fSJeeja KP multiplier; 255f7590d4fSJeeja KP } 256f7590d4fSJeeja KP 257db2f586bSSenthilnathan Veppur static u8 skl_tplg_be_dev_type(int dev_type) 258db2f586bSSenthilnathan Veppur { 259db2f586bSSenthilnathan Veppur int ret; 260db2f586bSSenthilnathan Veppur 261db2f586bSSenthilnathan Veppur switch (dev_type) { 262db2f586bSSenthilnathan Veppur case SKL_DEVICE_BT: 263db2f586bSSenthilnathan Veppur ret = NHLT_DEVICE_BT; 264db2f586bSSenthilnathan Veppur break; 265db2f586bSSenthilnathan Veppur 266db2f586bSSenthilnathan Veppur case SKL_DEVICE_DMIC: 267db2f586bSSenthilnathan Veppur ret = NHLT_DEVICE_DMIC; 268db2f586bSSenthilnathan Veppur break; 269db2f586bSSenthilnathan Veppur 270db2f586bSSenthilnathan Veppur case SKL_DEVICE_I2S: 271db2f586bSSenthilnathan Veppur ret = NHLT_DEVICE_I2S; 272db2f586bSSenthilnathan Veppur break; 273db2f586bSSenthilnathan Veppur 274db2f586bSSenthilnathan Veppur default: 275db2f586bSSenthilnathan Veppur ret = NHLT_DEVICE_INVALID; 276db2f586bSSenthilnathan Veppur break; 277db2f586bSSenthilnathan Veppur } 278db2f586bSSenthilnathan Veppur 279db2f586bSSenthilnathan Veppur return ret; 280db2f586bSSenthilnathan Veppur } 281db2f586bSSenthilnathan Veppur 2822d1419a3SJeeja KP static int skl_tplg_update_be_blob(struct snd_soc_dapm_widget *w, 283bcc2a2dcSCezary Rojewski struct skl_dev *skl) 2842d1419a3SJeeja KP { 2852d1419a3SJeeja KP struct skl_module_cfg *m_cfg = w->priv; 2862d1419a3SJeeja KP int link_type, dir; 2872d1419a3SJeeja KP u32 ch, s_freq, s_fmt; 2882d1419a3SJeeja KP struct nhlt_specific_cfg *cfg; 289db2f586bSSenthilnathan Veppur u8 dev_type = skl_tplg_be_dev_type(m_cfg->dev_type); 290f6fa56e2SRamesh Babu int fmt_idx = m_cfg->fmt_idx; 291f6fa56e2SRamesh Babu struct skl_module_iface *m_iface = &m_cfg->module->formats[fmt_idx]; 2922d1419a3SJeeja KP 2932d1419a3SJeeja KP /* check if we already have blob */ 2942d1419a3SJeeja KP if (m_cfg->formats_config.caps_size > 0) 2952d1419a3SJeeja KP return 0; 2962d1419a3SJeeja KP 297bcc2a2dcSCezary Rojewski dev_dbg(skl->dev, "Applying default cfg blob\n"); 2982d1419a3SJeeja KP switch (m_cfg->dev_type) { 2992d1419a3SJeeja KP case SKL_DEVICE_DMIC: 3002d1419a3SJeeja KP link_type = NHLT_LINK_DMIC; 301c7c6c736SJeeja KP dir = SNDRV_PCM_STREAM_CAPTURE; 302f6fa56e2SRamesh Babu s_freq = m_iface->inputs[0].fmt.s_freq; 303f6fa56e2SRamesh Babu s_fmt = m_iface->inputs[0].fmt.bit_depth; 304f6fa56e2SRamesh Babu ch = m_iface->inputs[0].fmt.channels; 3052d1419a3SJeeja KP break; 3062d1419a3SJeeja KP 3072d1419a3SJeeja KP case SKL_DEVICE_I2S: 3082d1419a3SJeeja KP link_type = NHLT_LINK_SSP; 3092d1419a3SJeeja KP if (m_cfg->hw_conn_type == SKL_CONN_SOURCE) { 310c7c6c736SJeeja KP dir = SNDRV_PCM_STREAM_PLAYBACK; 311f6fa56e2SRamesh Babu s_freq = m_iface->outputs[0].fmt.s_freq; 312f6fa56e2SRamesh Babu s_fmt = m_iface->outputs[0].fmt.bit_depth; 313f6fa56e2SRamesh Babu ch = m_iface->outputs[0].fmt.channels; 314c7c6c736SJeeja KP } else { 315c7c6c736SJeeja KP dir = SNDRV_PCM_STREAM_CAPTURE; 316f6fa56e2SRamesh Babu s_freq = m_iface->inputs[0].fmt.s_freq; 317f6fa56e2SRamesh Babu s_fmt = m_iface->inputs[0].fmt.bit_depth; 318f6fa56e2SRamesh Babu ch = m_iface->inputs[0].fmt.channels; 3192d1419a3SJeeja KP } 3202d1419a3SJeeja KP break; 3212d1419a3SJeeja KP 3222d1419a3SJeeja KP default: 3232d1419a3SJeeja KP return -EINVAL; 3242d1419a3SJeeja KP } 3252d1419a3SJeeja KP 3262d1419a3SJeeja KP /* update the blob based on virtual bus_id and default params */ 3272d1419a3SJeeja KP cfg = skl_get_ep_blob(skl, m_cfg->vbus_id, link_type, 328db2f586bSSenthilnathan Veppur s_fmt, ch, s_freq, dir, dev_type); 3292d1419a3SJeeja KP if (cfg) { 3302d1419a3SJeeja KP m_cfg->formats_config.caps_size = cfg->size; 3312d1419a3SJeeja KP m_cfg->formats_config.caps = (u32 *) &cfg->caps; 3322d1419a3SJeeja KP } else { 333bcc2a2dcSCezary Rojewski dev_err(skl->dev, "Blob NULL for id %x type %d dirn %d\n", 3342d1419a3SJeeja KP m_cfg->vbus_id, link_type, dir); 335bcc2a2dcSCezary Rojewski dev_err(skl->dev, "PCM: ch %d, freq %d, fmt %d\n", 3362d1419a3SJeeja KP ch, s_freq, s_fmt); 3372d1419a3SJeeja KP return -EIO; 3382d1419a3SJeeja KP } 3392d1419a3SJeeja KP 3402d1419a3SJeeja KP return 0; 3412d1419a3SJeeja KP } 3422d1419a3SJeeja KP 343f7590d4fSJeeja KP static void skl_tplg_update_module_params(struct snd_soc_dapm_widget *w, 344bcc2a2dcSCezary Rojewski struct skl_dev *skl) 345f7590d4fSJeeja KP { 346f7590d4fSJeeja KP struct skl_module_cfg *m_cfg = w->priv; 347f7590d4fSJeeja KP struct skl_pipe_params *params = m_cfg->pipe->p_params; 348f7590d4fSJeeja KP int p_conn_type = m_cfg->pipe->conn_type; 349f7590d4fSJeeja KP bool is_fe; 350f7590d4fSJeeja KP 351f7590d4fSJeeja KP if (!m_cfg->params_fixup) 352f7590d4fSJeeja KP return; 353f7590d4fSJeeja KP 354bcc2a2dcSCezary Rojewski dev_dbg(skl->dev, "Mconfig for widget=%s BEFORE updation\n", 355f7590d4fSJeeja KP w->name); 356f7590d4fSJeeja KP 357bcc2a2dcSCezary Rojewski skl_dump_mconfig(skl, m_cfg); 358f7590d4fSJeeja KP 359f7590d4fSJeeja KP if (p_conn_type == SKL_PIPE_CONN_TYPE_FE) 360f7590d4fSJeeja KP is_fe = true; 361f7590d4fSJeeja KP else 362f7590d4fSJeeja KP is_fe = false; 363f7590d4fSJeeja KP 364f7590d4fSJeeja KP skl_tplg_update_params_fixup(m_cfg, params, is_fe); 365bcc2a2dcSCezary Rojewski skl_tplg_update_buffer_size(skl, m_cfg); 366f7590d4fSJeeja KP 367bcc2a2dcSCezary Rojewski dev_dbg(skl->dev, "Mconfig for widget=%s AFTER updation\n", 368f7590d4fSJeeja KP w->name); 369f7590d4fSJeeja KP 370bcc2a2dcSCezary Rojewski skl_dump_mconfig(skl, m_cfg); 371f7590d4fSJeeja KP } 372f7590d4fSJeeja KP 373e4e2d2f4SJeeja KP /* 374abb74003SJeeja KP * some modules can have multiple params set from user control and 375abb74003SJeeja KP * need to be set after module is initialized. If set_param flag is 376abb74003SJeeja KP * set module params will be done after module is initialised. 377abb74003SJeeja KP */ 378abb74003SJeeja KP static int skl_tplg_set_module_params(struct snd_soc_dapm_widget *w, 379bcc2a2dcSCezary Rojewski struct skl_dev *skl) 380abb74003SJeeja KP { 381abb74003SJeeja KP int i, ret; 382abb74003SJeeja KP struct skl_module_cfg *mconfig = w->priv; 383abb74003SJeeja KP const struct snd_kcontrol_new *k; 384abb74003SJeeja KP struct soc_bytes_ext *sb; 385abb74003SJeeja KP struct skl_algo_data *bc; 386abb74003SJeeja KP struct skl_specific_cfg *sp_cfg; 387abb74003SJeeja KP 388abb74003SJeeja KP if (mconfig->formats_config.caps_size > 0 && 3894ced1827SJeeja KP mconfig->formats_config.set_params == SKL_PARAM_SET) { 390abb74003SJeeja KP sp_cfg = &mconfig->formats_config; 391bcc2a2dcSCezary Rojewski ret = skl_set_module_params(skl, sp_cfg->caps, 392abb74003SJeeja KP sp_cfg->caps_size, 393abb74003SJeeja KP sp_cfg->param_id, mconfig); 394abb74003SJeeja KP if (ret < 0) 395abb74003SJeeja KP return ret; 396abb74003SJeeja KP } 397abb74003SJeeja KP 398abb74003SJeeja KP for (i = 0; i < w->num_kcontrols; i++) { 399abb74003SJeeja KP k = &w->kcontrol_news[i]; 400abb74003SJeeja KP if (k->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { 401abb74003SJeeja KP sb = (void *) k->private_value; 402abb74003SJeeja KP bc = (struct skl_algo_data *)sb->dobj.private; 403abb74003SJeeja KP 4044ced1827SJeeja KP if (bc->set_params == SKL_PARAM_SET) { 405bcc2a2dcSCezary Rojewski ret = skl_set_module_params(skl, 4060d682104SDharageswari R (u32 *)bc->params, bc->size, 407abb74003SJeeja KP bc->param_id, mconfig); 408abb74003SJeeja KP if (ret < 0) 409abb74003SJeeja KP return ret; 410abb74003SJeeja KP } 411abb74003SJeeja KP } 412abb74003SJeeja KP } 413abb74003SJeeja KP 414abb74003SJeeja KP return 0; 415abb74003SJeeja KP } 416abb74003SJeeja KP 417abb74003SJeeja KP /* 418abb74003SJeeja KP * some module param can set from user control and this is required as 419abb74003SJeeja KP * when module is initailzed. if module param is required in init it is 420abb74003SJeeja KP * identifed by set_param flag. if set_param flag is not set, then this 421abb74003SJeeja KP * parameter needs to set as part of module init. 422abb74003SJeeja KP */ 423abb74003SJeeja KP static int skl_tplg_set_module_init_data(struct snd_soc_dapm_widget *w) 424abb74003SJeeja KP { 425abb74003SJeeja KP const struct snd_kcontrol_new *k; 426abb74003SJeeja KP struct soc_bytes_ext *sb; 427abb74003SJeeja KP struct skl_algo_data *bc; 428abb74003SJeeja KP struct skl_module_cfg *mconfig = w->priv; 429abb74003SJeeja KP int i; 430abb74003SJeeja KP 431abb74003SJeeja KP for (i = 0; i < w->num_kcontrols; i++) { 432abb74003SJeeja KP k = &w->kcontrol_news[i]; 433abb74003SJeeja KP if (k->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { 434abb74003SJeeja KP sb = (struct soc_bytes_ext *)k->private_value; 435abb74003SJeeja KP bc = (struct skl_algo_data *)sb->dobj.private; 436abb74003SJeeja KP 4374ced1827SJeeja KP if (bc->set_params != SKL_PARAM_INIT) 438abb74003SJeeja KP continue; 439abb74003SJeeja KP 440d1a6fe41STakashi Sakamoto mconfig->formats_config.caps = (u32 *)bc->params; 4410d682104SDharageswari R mconfig->formats_config.caps_size = bc->size; 442abb74003SJeeja KP 443abb74003SJeeja KP break; 444abb74003SJeeja KP } 445abb74003SJeeja KP } 446abb74003SJeeja KP 447abb74003SJeeja KP return 0; 448abb74003SJeeja KP } 449abb74003SJeeja KP 450bcc2a2dcSCezary Rojewski static int skl_tplg_module_prepare(struct skl_dev *skl, struct skl_pipe *pipe, 451bb704a73SJeeja KP struct snd_soc_dapm_widget *w, struct skl_module_cfg *mcfg) 452bb704a73SJeeja KP { 453bb704a73SJeeja KP switch (mcfg->dev_type) { 454bb704a73SJeeja KP case SKL_DEVICE_HDAHOST: 455bcc2a2dcSCezary Rojewski return skl_pcm_host_dma_prepare(skl->dev, pipe->p_params); 456bb704a73SJeeja KP 457bb704a73SJeeja KP case SKL_DEVICE_HDALINK: 458bcc2a2dcSCezary Rojewski return skl_pcm_link_dma_prepare(skl->dev, pipe->p_params); 459bb704a73SJeeja KP } 460bb704a73SJeeja KP 461bb704a73SJeeja KP return 0; 462bb704a73SJeeja KP } 463bb704a73SJeeja KP 464abb74003SJeeja KP /* 465e4e2d2f4SJeeja KP * Inside a pipe instance, we can have various modules. These modules need 466e4e2d2f4SJeeja KP * to instantiated in DSP by invoking INIT_MODULE IPC, which is achieved by 467e4e2d2f4SJeeja KP * skl_init_module() routine, so invoke that for all modules in a pipeline 468e4e2d2f4SJeeja KP */ 469e4e2d2f4SJeeja KP static int 470bcc2a2dcSCezary Rojewski skl_tplg_init_pipe_modules(struct skl_dev *skl, struct skl_pipe *pipe) 471e4e2d2f4SJeeja KP { 472e4e2d2f4SJeeja KP struct skl_pipe_module *w_module; 473e4e2d2f4SJeeja KP struct snd_soc_dapm_widget *w; 474e4e2d2f4SJeeja KP struct skl_module_cfg *mconfig; 475f6fa56e2SRamesh Babu u8 cfg_idx; 476e4e2d2f4SJeeja KP int ret = 0; 477e4e2d2f4SJeeja KP 478e4e2d2f4SJeeja KP list_for_each_entry(w_module, &pipe->w_list, node) { 4799e0784d0SAndy Shevchenko guid_t *uuid_mod; 480e4e2d2f4SJeeja KP w = w_module->w; 481e4e2d2f4SJeeja KP mconfig = w->priv; 482e4e2d2f4SJeeja KP 483b7c50555SVinod Koul /* check if module ids are populated */ 484b7c50555SVinod Koul if (mconfig->id.module_id < 0) { 485bcc2a2dcSCezary Rojewski dev_err(skl->dev, 486a657ae7eSVinod Koul "module %pUL id not populated\n", 4879e0784d0SAndy Shevchenko (guid_t *)mconfig->guid); 488a657ae7eSVinod Koul return -EIO; 489b7c50555SVinod Koul } 490b7c50555SVinod Koul 491f6fa56e2SRamesh Babu cfg_idx = mconfig->pipe->cur_config_idx; 492f6fa56e2SRamesh Babu mconfig->fmt_idx = mconfig->mod_cfg[cfg_idx].fmt_idx; 493f6fa56e2SRamesh Babu mconfig->res_idx = mconfig->mod_cfg[cfg_idx].res_idx; 494f6fa56e2SRamesh Babu 495bcc2a2dcSCezary Rojewski if (mconfig->module->loadable && skl->dsp->fw_ops.load_mod) { 496bcc2a2dcSCezary Rojewski ret = skl->dsp->fw_ops.load_mod(skl->dsp, 4976c5768b3SDharageswari R mconfig->id.module_id, mconfig->guid); 4986c5768b3SDharageswari R if (ret < 0) 4996c5768b3SDharageswari R return ret; 500d643678bSJeeja KP 501d643678bSJeeja KP mconfig->m_state = SKL_MODULE_LOADED; 5026c5768b3SDharageswari R } 5036c5768b3SDharageswari R 504bb704a73SJeeja KP /* prepare the DMA if the module is gateway cpr */ 505bcc2a2dcSCezary Rojewski ret = skl_tplg_module_prepare(skl, pipe, w, mconfig); 506bb704a73SJeeja KP if (ret < 0) 507bb704a73SJeeja KP return ret; 508bb704a73SJeeja KP 5092d1419a3SJeeja KP /* update blob if blob is null for be with default value */ 510bcc2a2dcSCezary Rojewski skl_tplg_update_be_blob(w, skl); 5112d1419a3SJeeja KP 512f7590d4fSJeeja KP /* 513f7590d4fSJeeja KP * apply fix/conversion to module params based on 514f7590d4fSJeeja KP * FE/BE params 515f7590d4fSJeeja KP */ 516bcc2a2dcSCezary Rojewski skl_tplg_update_module_params(w, skl); 5179e0784d0SAndy Shevchenko uuid_mod = (guid_t *)mconfig->guid; 518bcc2a2dcSCezary Rojewski mconfig->id.pvt_id = skl_get_pvt_id(skl, uuid_mod, 519b26199eaSJeeja KP mconfig->id.instance_id); 520ef2a352cSDharageswari R if (mconfig->id.pvt_id < 0) 521ef2a352cSDharageswari R return ret; 522abb74003SJeeja KP skl_tplg_set_module_init_data(w); 5234147a6e5SPardha Saradhi K 524bcc2a2dcSCezary Rojewski ret = skl_dsp_get_core(skl->dsp, mconfig->core_id); 5254147a6e5SPardha Saradhi K if (ret < 0) { 526bcc2a2dcSCezary Rojewski dev_err(skl->dev, "Failed to wake up core %d ret=%d\n", 5274147a6e5SPardha Saradhi K mconfig->core_id, ret); 5284147a6e5SPardha Saradhi K return ret; 5294147a6e5SPardha Saradhi K } 5304147a6e5SPardha Saradhi K 531bcc2a2dcSCezary Rojewski ret = skl_init_module(skl, mconfig); 532ef2a352cSDharageswari R if (ret < 0) { 533bcc2a2dcSCezary Rojewski skl_put_pvt_id(skl, uuid_mod, &mconfig->id.pvt_id); 5344147a6e5SPardha Saradhi K goto err; 535ef2a352cSDharageswari R } 536f2a167caSCezary Rojewski 537bcc2a2dcSCezary Rojewski ret = skl_tplg_set_module_params(w, skl); 538e4e2d2f4SJeeja KP if (ret < 0) 5394147a6e5SPardha Saradhi K goto err; 540e4e2d2f4SJeeja KP } 541e4e2d2f4SJeeja KP 542e4e2d2f4SJeeja KP return 0; 5434147a6e5SPardha Saradhi K err: 544bcc2a2dcSCezary Rojewski skl_dsp_put_core(skl->dsp, mconfig->core_id); 5454147a6e5SPardha Saradhi K return ret; 546e4e2d2f4SJeeja KP } 547d93f8e55SVinod Koul 548bcc2a2dcSCezary Rojewski static int skl_tplg_unload_pipe_modules(struct skl_dev *skl, 5496c5768b3SDharageswari R struct skl_pipe *pipe) 5506c5768b3SDharageswari R { 5514147a6e5SPardha Saradhi K int ret = 0; 5526c5768b3SDharageswari R struct skl_pipe_module *w_module = NULL; 5536c5768b3SDharageswari R struct skl_module_cfg *mconfig = NULL; 5546c5768b3SDharageswari R 5556c5768b3SDharageswari R list_for_each_entry(w_module, &pipe->w_list, node) { 5569e0784d0SAndy Shevchenko guid_t *uuid_mod; 5576c5768b3SDharageswari R mconfig = w_module->w->priv; 5589e0784d0SAndy Shevchenko uuid_mod = (guid_t *)mconfig->guid; 5596c5768b3SDharageswari R 560bcc2a2dcSCezary Rojewski if (mconfig->module->loadable && skl->dsp->fw_ops.unload_mod && 561b0fab9c6SDharageswari R mconfig->m_state > SKL_MODULE_UNINIT) { 562bcc2a2dcSCezary Rojewski ret = skl->dsp->fw_ops.unload_mod(skl->dsp, 5636c5768b3SDharageswari R mconfig->id.module_id); 564b0fab9c6SDharageswari R if (ret < 0) 565b0fab9c6SDharageswari R return -EIO; 566b0fab9c6SDharageswari R } 567bcc2a2dcSCezary Rojewski skl_put_pvt_id(skl, uuid_mod, &mconfig->id.pvt_id); 5684147a6e5SPardha Saradhi K 569bcc2a2dcSCezary Rojewski ret = skl_dsp_put_core(skl->dsp, mconfig->core_id); 5704147a6e5SPardha Saradhi K if (ret < 0) { 5714147a6e5SPardha Saradhi K /* don't return; continue with other modules */ 572bcc2a2dcSCezary Rojewski dev_err(skl->dev, "Failed to sleep core %d ret=%d\n", 5734147a6e5SPardha Saradhi K mconfig->core_id, ret); 5744147a6e5SPardha Saradhi K } 5756c5768b3SDharageswari R } 5766c5768b3SDharageswari R 5776c5768b3SDharageswari R /* no modules to unload in this path, so return */ 5784147a6e5SPardha Saradhi K return ret; 5796c5768b3SDharageswari R } 5806c5768b3SDharageswari R 581d93f8e55SVinod Koul /* 582f6fa56e2SRamesh Babu * Here, we select pipe format based on the pipe type and pipe 583f6fa56e2SRamesh Babu * direction to determine the current config index for the pipeline. 584f6fa56e2SRamesh Babu * The config index is then used to select proper module resources. 585f6fa56e2SRamesh Babu * Intermediate pipes currently have a fixed format hence we select the 586f6fa56e2SRamesh Babu * 0th configuratation by default for such pipes. 587f6fa56e2SRamesh Babu */ 588f6fa56e2SRamesh Babu static int 589bcc2a2dcSCezary Rojewski skl_tplg_get_pipe_config(struct skl_dev *skl, struct skl_module_cfg *mconfig) 590f6fa56e2SRamesh Babu { 591f6fa56e2SRamesh Babu struct skl_pipe *pipe = mconfig->pipe; 592f6fa56e2SRamesh Babu struct skl_pipe_params *params = pipe->p_params; 593f6fa56e2SRamesh Babu struct skl_path_config *pconfig = &pipe->configs[0]; 594f6fa56e2SRamesh Babu struct skl_pipe_fmt *fmt = NULL; 595f6fa56e2SRamesh Babu bool in_fmt = false; 596f6fa56e2SRamesh Babu int i; 597f6fa56e2SRamesh Babu 598f6fa56e2SRamesh Babu if (pipe->nr_cfgs == 0) { 599f6fa56e2SRamesh Babu pipe->cur_config_idx = 0; 600f6fa56e2SRamesh Babu return 0; 601f6fa56e2SRamesh Babu } 602f6fa56e2SRamesh Babu 603f6fa56e2SRamesh Babu if (pipe->conn_type == SKL_PIPE_CONN_TYPE_NONE) { 604bcc2a2dcSCezary Rojewski dev_dbg(skl->dev, "No conn_type detected, take 0th config\n"); 605f6fa56e2SRamesh Babu pipe->cur_config_idx = 0; 606f6fa56e2SRamesh Babu pipe->memory_pages = pconfig->mem_pages; 607f6fa56e2SRamesh Babu 608f6fa56e2SRamesh Babu return 0; 609f6fa56e2SRamesh Babu } 610f6fa56e2SRamesh Babu 611f6fa56e2SRamesh Babu if ((pipe->conn_type == SKL_PIPE_CONN_TYPE_FE && 612f6fa56e2SRamesh Babu pipe->direction == SNDRV_PCM_STREAM_PLAYBACK) || 613f6fa56e2SRamesh Babu (pipe->conn_type == SKL_PIPE_CONN_TYPE_BE && 614f6fa56e2SRamesh Babu pipe->direction == SNDRV_PCM_STREAM_CAPTURE)) 615f6fa56e2SRamesh Babu in_fmt = true; 616f6fa56e2SRamesh Babu 617f6fa56e2SRamesh Babu for (i = 0; i < pipe->nr_cfgs; i++) { 618f6fa56e2SRamesh Babu pconfig = &pipe->configs[i]; 619f6fa56e2SRamesh Babu if (in_fmt) 620f6fa56e2SRamesh Babu fmt = &pconfig->in_fmt; 621f6fa56e2SRamesh Babu else 622f6fa56e2SRamesh Babu fmt = &pconfig->out_fmt; 623f6fa56e2SRamesh Babu 624f6fa56e2SRamesh Babu if (CHECK_HW_PARAMS(params->ch, params->s_freq, params->s_fmt, 625f6fa56e2SRamesh Babu fmt->channels, fmt->freq, fmt->bps)) { 626f6fa56e2SRamesh Babu pipe->cur_config_idx = i; 627f6fa56e2SRamesh Babu pipe->memory_pages = pconfig->mem_pages; 628bcc2a2dcSCezary Rojewski dev_dbg(skl->dev, "Using pipe config: %d\n", i); 629f6fa56e2SRamesh Babu 630f6fa56e2SRamesh Babu return 0; 631f6fa56e2SRamesh Babu } 632f6fa56e2SRamesh Babu } 633f6fa56e2SRamesh Babu 634bcc2a2dcSCezary Rojewski dev_err(skl->dev, "Invalid pipe config: %d %d %d for pipe: %d\n", 635f6fa56e2SRamesh Babu params->ch, params->s_freq, params->s_fmt, pipe->ppl_id); 636f6fa56e2SRamesh Babu return -EINVAL; 637f6fa56e2SRamesh Babu } 638f6fa56e2SRamesh Babu 639f6fa56e2SRamesh Babu /* 640d93f8e55SVinod Koul * Mixer module represents a pipeline. So in the Pre-PMU event of mixer we 641d93f8e55SVinod Koul * need create the pipeline. So we do following: 642d93f8e55SVinod Koul * - Create the pipeline 643d93f8e55SVinod Koul * - Initialize the modules in pipeline 644d93f8e55SVinod Koul * - finally bind all modules together 645d93f8e55SVinod Koul */ 646d93f8e55SVinod Koul static int skl_tplg_mixer_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w, 647bcc2a2dcSCezary Rojewski struct skl_dev *skl) 648d93f8e55SVinod Koul { 649d93f8e55SVinod Koul int ret; 650d93f8e55SVinod Koul struct skl_module_cfg *mconfig = w->priv; 651d93f8e55SVinod Koul struct skl_pipe_module *w_module; 652d93f8e55SVinod Koul struct skl_pipe *s_pipe = mconfig->pipe; 653b8c722ddSJeeja KP struct skl_module_cfg *src_module = NULL, *dst_module, *module; 654b8c722ddSJeeja KP struct skl_module_deferred_bind *modules; 655d93f8e55SVinod Koul 656f6fa56e2SRamesh Babu ret = skl_tplg_get_pipe_config(skl, mconfig); 657f6fa56e2SRamesh Babu if (ret < 0) 658f6fa56e2SRamesh Babu return ret; 659f6fa56e2SRamesh Babu 660d93f8e55SVinod Koul /* 661d93f8e55SVinod Koul * Create a list of modules for pipe. 662d93f8e55SVinod Koul * This list contains modules from source to sink 663d93f8e55SVinod Koul */ 664bcc2a2dcSCezary Rojewski ret = skl_create_pipeline(skl, mconfig->pipe); 665d93f8e55SVinod Koul if (ret < 0) 666d93f8e55SVinod Koul return ret; 667d93f8e55SVinod Koul 668d93f8e55SVinod Koul /* Init all pipe modules from source to sink */ 669d93f8e55SVinod Koul ret = skl_tplg_init_pipe_modules(skl, s_pipe); 670d93f8e55SVinod Koul if (ret < 0) 671d93f8e55SVinod Koul return ret; 672d93f8e55SVinod Koul 673d93f8e55SVinod Koul /* Bind modules from source to sink */ 674d93f8e55SVinod Koul list_for_each_entry(w_module, &s_pipe->w_list, node) { 675d93f8e55SVinod Koul dst_module = w_module->w->priv; 676d93f8e55SVinod Koul 677d93f8e55SVinod Koul if (src_module == NULL) { 678d93f8e55SVinod Koul src_module = dst_module; 679d93f8e55SVinod Koul continue; 680d93f8e55SVinod Koul } 681d93f8e55SVinod Koul 682bcc2a2dcSCezary Rojewski ret = skl_bind_modules(skl, src_module, dst_module); 683d93f8e55SVinod Koul if (ret < 0) 684d93f8e55SVinod Koul return ret; 685d93f8e55SVinod Koul 686d93f8e55SVinod Koul src_module = dst_module; 687d93f8e55SVinod Koul } 688d93f8e55SVinod Koul 689b8c722ddSJeeja KP /* 690b8c722ddSJeeja KP * When the destination module is initialized, check for these modules 691b8c722ddSJeeja KP * in deferred bind list. If found, bind them. 692b8c722ddSJeeja KP */ 693b8c722ddSJeeja KP list_for_each_entry(w_module, &s_pipe->w_list, node) { 694b8c722ddSJeeja KP if (list_empty(&skl->bind_list)) 695b8c722ddSJeeja KP break; 696b8c722ddSJeeja KP 697b8c722ddSJeeja KP list_for_each_entry(modules, &skl->bind_list, node) { 698b8c722ddSJeeja KP module = w_module->w->priv; 699b8c722ddSJeeja KP if (modules->dst == module) 700bcc2a2dcSCezary Rojewski skl_bind_modules(skl, modules->src, 701b8c722ddSJeeja KP modules->dst); 702b8c722ddSJeeja KP } 703b8c722ddSJeeja KP } 704b8c722ddSJeeja KP 705d93f8e55SVinod Koul return 0; 706d93f8e55SVinod Koul } 707d93f8e55SVinod Koul 708bcc2a2dcSCezary Rojewski static int skl_fill_sink_instance_id(struct skl_dev *skl, u32 *params, 709bf3e5ef5SDharageswari R int size, struct skl_module_cfg *mcfg) 7105e8f0ee4SDharageswari R { 7115e8f0ee4SDharageswari R int i, pvt_id; 7125e8f0ee4SDharageswari R 713bf3e5ef5SDharageswari R if (mcfg->m_type == SKL_MODULE_TYPE_KPB) { 714bf3e5ef5SDharageswari R struct skl_kpb_params *kpb_params = 715bf3e5ef5SDharageswari R (struct skl_kpb_params *)params; 716f7a9f772SSriram Periyasamy struct skl_mod_inst_map *inst = kpb_params->u.map; 7175e8f0ee4SDharageswari R 718bf3e5ef5SDharageswari R for (i = 0; i < kpb_params->num_modules; i++) { 719bcc2a2dcSCezary Rojewski pvt_id = skl_get_pvt_instance_id_map(skl, inst->mod_id, 720bf3e5ef5SDharageswari R inst->inst_id); 7215e8f0ee4SDharageswari R if (pvt_id < 0) 7225e8f0ee4SDharageswari R return -EINVAL; 723bf3e5ef5SDharageswari R 7245e8f0ee4SDharageswari R inst->inst_id = pvt_id; 7255e8f0ee4SDharageswari R inst++; 7265e8f0ee4SDharageswari R } 7275e8f0ee4SDharageswari R } 7285e8f0ee4SDharageswari R 729bf3e5ef5SDharageswari R return 0; 730bf3e5ef5SDharageswari R } 731cc6a4044SJeeja KP /* 732cc6a4044SJeeja KP * Some modules require params to be set after the module is bound to 733cc6a4044SJeeja KP * all pins connected. 734cc6a4044SJeeja KP * 735cc6a4044SJeeja KP * The module provider initializes set_param flag for such modules and we 736cc6a4044SJeeja KP * send params after binding 737cc6a4044SJeeja KP */ 738cc6a4044SJeeja KP static int skl_tplg_set_module_bind_params(struct snd_soc_dapm_widget *w, 739bcc2a2dcSCezary Rojewski struct skl_module_cfg *mcfg, struct skl_dev *skl) 740cc6a4044SJeeja KP { 741cc6a4044SJeeja KP int i, ret; 742cc6a4044SJeeja KP struct skl_module_cfg *mconfig = w->priv; 743cc6a4044SJeeja KP const struct snd_kcontrol_new *k; 744cc6a4044SJeeja KP struct soc_bytes_ext *sb; 745cc6a4044SJeeja KP struct skl_algo_data *bc; 746cc6a4044SJeeja KP struct skl_specific_cfg *sp_cfg; 747bf3e5ef5SDharageswari R u32 *params; 748cc6a4044SJeeja KP 749cc6a4044SJeeja KP /* 750cc6a4044SJeeja KP * check all out/in pins are in bind state. 751cc6a4044SJeeja KP * if so set the module param 752cc6a4044SJeeja KP */ 753f6fa56e2SRamesh Babu for (i = 0; i < mcfg->module->max_output_pins; i++) { 754cc6a4044SJeeja KP if (mcfg->m_out_pin[i].pin_state != SKL_PIN_BIND_DONE) 755cc6a4044SJeeja KP return 0; 756cc6a4044SJeeja KP } 757cc6a4044SJeeja KP 758f6fa56e2SRamesh Babu for (i = 0; i < mcfg->module->max_input_pins; i++) { 759cc6a4044SJeeja KP if (mcfg->m_in_pin[i].pin_state != SKL_PIN_BIND_DONE) 760cc6a4044SJeeja KP return 0; 761cc6a4044SJeeja KP } 762cc6a4044SJeeja KP 763cc6a4044SJeeja KP if (mconfig->formats_config.caps_size > 0 && 764cc6a4044SJeeja KP mconfig->formats_config.set_params == SKL_PARAM_BIND) { 765cc6a4044SJeeja KP sp_cfg = &mconfig->formats_config; 766bcc2a2dcSCezary Rojewski ret = skl_set_module_params(skl, sp_cfg->caps, 767cc6a4044SJeeja KP sp_cfg->caps_size, 768cc6a4044SJeeja KP sp_cfg->param_id, mconfig); 769cc6a4044SJeeja KP if (ret < 0) 770cc6a4044SJeeja KP return ret; 771cc6a4044SJeeja KP } 772cc6a4044SJeeja KP 773cc6a4044SJeeja KP for (i = 0; i < w->num_kcontrols; i++) { 774cc6a4044SJeeja KP k = &w->kcontrol_news[i]; 775cc6a4044SJeeja KP if (k->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { 776cc6a4044SJeeja KP sb = (void *) k->private_value; 777cc6a4044SJeeja KP bc = (struct skl_algo_data *)sb->dobj.private; 778cc6a4044SJeeja KP 779cc6a4044SJeeja KP if (bc->set_params == SKL_PARAM_BIND) { 780ca92cc46Szhong jiang params = kmemdup(bc->params, bc->max, GFP_KERNEL); 781bf3e5ef5SDharageswari R if (!params) 782bf3e5ef5SDharageswari R return -ENOMEM; 783bf3e5ef5SDharageswari R 784bcc2a2dcSCezary Rojewski skl_fill_sink_instance_id(skl, params, bc->max, 785bf3e5ef5SDharageswari R mconfig); 786bf3e5ef5SDharageswari R 787bcc2a2dcSCezary Rojewski ret = skl_set_module_params(skl, params, 788bf3e5ef5SDharageswari R bc->max, bc->param_id, mconfig); 789bf3e5ef5SDharageswari R kfree(params); 790bf3e5ef5SDharageswari R 791cc6a4044SJeeja KP if (ret < 0) 792cc6a4044SJeeja KP return ret; 793cc6a4044SJeeja KP } 794cc6a4044SJeeja KP } 795cc6a4044SJeeja KP } 796cc6a4044SJeeja KP 797cc6a4044SJeeja KP return 0; 798cc6a4044SJeeja KP } 799cc6a4044SJeeja KP 800bcc2a2dcSCezary Rojewski static int skl_get_module_id(struct skl_dev *skl, guid_t *uuid) 801f7a9f772SSriram Periyasamy { 802f7a9f772SSriram Periyasamy struct uuid_module *module; 803f7a9f772SSriram Periyasamy 804bcc2a2dcSCezary Rojewski list_for_each_entry(module, &skl->uuid_list, list) { 8059e0784d0SAndy Shevchenko if (guid_equal(uuid, &module->uuid)) 806f7a9f772SSriram Periyasamy return module->id; 807f7a9f772SSriram Periyasamy } 808f7a9f772SSriram Periyasamy 809f7a9f772SSriram Periyasamy return -EINVAL; 810f7a9f772SSriram Periyasamy } 811f7a9f772SSriram Periyasamy 812bcc2a2dcSCezary Rojewski static int skl_tplg_find_moduleid_from_uuid(struct skl_dev *skl, 813f7a9f772SSriram Periyasamy const struct snd_kcontrol_new *k) 814f7a9f772SSriram Periyasamy { 815f7a9f772SSriram Periyasamy struct soc_bytes_ext *sb = (void *) k->private_value; 816f7a9f772SSriram Periyasamy struct skl_algo_data *bc = (struct skl_algo_data *)sb->dobj.private; 817f7a9f772SSriram Periyasamy struct skl_kpb_params *uuid_params, *params; 81876f56faeSRakesh Ughreja struct hdac_bus *bus = skl_to_bus(skl); 819f7a9f772SSriram Periyasamy int i, size, module_id; 820f7a9f772SSriram Periyasamy 821f7a9f772SSriram Periyasamy if (bc->set_params == SKL_PARAM_BIND && bc->max) { 822f7a9f772SSriram Periyasamy uuid_params = (struct skl_kpb_params *)bc->params; 823d00cc2f1SGustavo A. R. Silva size = struct_size(params, u.map, uuid_params->num_modules); 824f7a9f772SSriram Periyasamy 825f7a9f772SSriram Periyasamy params = devm_kzalloc(bus->dev, size, GFP_KERNEL); 826f7a9f772SSriram Periyasamy if (!params) 827f7a9f772SSriram Periyasamy return -ENOMEM; 828f7a9f772SSriram Periyasamy 829f7a9f772SSriram Periyasamy params->num_modules = uuid_params->num_modules; 830f7a9f772SSriram Periyasamy 831f7a9f772SSriram Periyasamy for (i = 0; i < uuid_params->num_modules; i++) { 832bcc2a2dcSCezary Rojewski module_id = skl_get_module_id(skl, 833f7a9f772SSriram Periyasamy &uuid_params->u.map_uuid[i].mod_uuid); 834f7a9f772SSriram Periyasamy if (module_id < 0) { 835f7a9f772SSriram Periyasamy devm_kfree(bus->dev, params); 836f7a9f772SSriram Periyasamy return -EINVAL; 837f7a9f772SSriram Periyasamy } 838f7a9f772SSriram Periyasamy 839f7a9f772SSriram Periyasamy params->u.map[i].mod_id = module_id; 840f7a9f772SSriram Periyasamy params->u.map[i].inst_id = 841f7a9f772SSriram Periyasamy uuid_params->u.map_uuid[i].inst_id; 842f7a9f772SSriram Periyasamy } 843f7a9f772SSriram Periyasamy 844f7a9f772SSriram Periyasamy devm_kfree(bus->dev, bc->params); 845f7a9f772SSriram Periyasamy bc->params = (char *)params; 846f7a9f772SSriram Periyasamy bc->max = size; 847f7a9f772SSriram Periyasamy } 848f7a9f772SSriram Periyasamy 849f7a9f772SSriram Periyasamy return 0; 850f7a9f772SSriram Periyasamy } 851f7a9f772SSriram Periyasamy 852f7a9f772SSriram Periyasamy /* 853f7a9f772SSriram Periyasamy * Retrieve the module id from UUID mentioned in the 854f7a9f772SSriram Periyasamy * post bind params 855f7a9f772SSriram Periyasamy */ 856bcc2a2dcSCezary Rojewski void skl_tplg_add_moduleid_in_bind_params(struct skl_dev *skl, 857f7a9f772SSriram Periyasamy struct snd_soc_dapm_widget *w) 858f7a9f772SSriram Periyasamy { 859f7a9f772SSriram Periyasamy struct skl_module_cfg *mconfig = w->priv; 860f7a9f772SSriram Periyasamy int i; 861f7a9f772SSriram Periyasamy 862f7a9f772SSriram Periyasamy /* 863f7a9f772SSriram Periyasamy * Post bind params are used for only for KPB 864f7a9f772SSriram Periyasamy * to set copier instances to drain the data 865f7a9f772SSriram Periyasamy * in fast mode 866f7a9f772SSriram Periyasamy */ 867f7a9f772SSriram Periyasamy if (mconfig->m_type != SKL_MODULE_TYPE_KPB) 868f7a9f772SSriram Periyasamy return; 869f7a9f772SSriram Periyasamy 870f7a9f772SSriram Periyasamy for (i = 0; i < w->num_kcontrols; i++) 871f7a9f772SSriram Periyasamy if ((w->kcontrol_news[i].access & 872f7a9f772SSriram Periyasamy SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) && 873f7a9f772SSriram Periyasamy (skl_tplg_find_moduleid_from_uuid(skl, 874f7a9f772SSriram Periyasamy &w->kcontrol_news[i]) < 0)) 875bcc2a2dcSCezary Rojewski dev_err(skl->dev, 876f7a9f772SSriram Periyasamy "%s: invalid kpb post bind params\n", 877f7a9f772SSriram Periyasamy __func__); 878f7a9f772SSriram Periyasamy } 879b8c722ddSJeeja KP 880bcc2a2dcSCezary Rojewski static int skl_tplg_module_add_deferred_bind(struct skl_dev *skl, 881b8c722ddSJeeja KP struct skl_module_cfg *src, struct skl_module_cfg *dst) 882b8c722ddSJeeja KP { 883b8c722ddSJeeja KP struct skl_module_deferred_bind *m_list, *modules; 884b8c722ddSJeeja KP int i; 885b8c722ddSJeeja KP 886b8c722ddSJeeja KP /* only supported for module with static pin connection */ 887f6fa56e2SRamesh Babu for (i = 0; i < dst->module->max_input_pins; i++) { 888b8c722ddSJeeja KP struct skl_module_pin *pin = &dst->m_in_pin[i]; 889b8c722ddSJeeja KP 890b8c722ddSJeeja KP if (pin->is_dynamic) 891b8c722ddSJeeja KP continue; 892b8c722ddSJeeja KP 893b8c722ddSJeeja KP if ((pin->id.module_id == src->id.module_id) && 894b8c722ddSJeeja KP (pin->id.instance_id == src->id.instance_id)) { 895b8c722ddSJeeja KP 896b8c722ddSJeeja KP if (!list_empty(&skl->bind_list)) { 897b8c722ddSJeeja KP list_for_each_entry(modules, &skl->bind_list, node) { 898b8c722ddSJeeja KP if (modules->src == src && modules->dst == dst) 899b8c722ddSJeeja KP return 0; 900b8c722ddSJeeja KP } 901b8c722ddSJeeja KP } 902b8c722ddSJeeja KP 903b8c722ddSJeeja KP m_list = kzalloc(sizeof(*m_list), GFP_KERNEL); 904b8c722ddSJeeja KP if (!m_list) 905b8c722ddSJeeja KP return -ENOMEM; 906b8c722ddSJeeja KP 907b8c722ddSJeeja KP m_list->src = src; 908b8c722ddSJeeja KP m_list->dst = dst; 909b8c722ddSJeeja KP 910b8c722ddSJeeja KP list_add(&m_list->node, &skl->bind_list); 911b8c722ddSJeeja KP } 912b8c722ddSJeeja KP } 913b8c722ddSJeeja KP 914b8c722ddSJeeja KP return 0; 915b8c722ddSJeeja KP } 916b8c722ddSJeeja KP 9178724ff17SJeeja KP static int skl_tplg_bind_sinks(struct snd_soc_dapm_widget *w, 918bcc2a2dcSCezary Rojewski struct skl_dev *skl, 9196bd4cf85SJeeja KP struct snd_soc_dapm_widget *src_w, 9208724ff17SJeeja KP struct skl_module_cfg *src_mconfig) 921d93f8e55SVinod Koul { 922d93f8e55SVinod Koul struct snd_soc_dapm_path *p; 9230ed95d76SJeeja KP struct snd_soc_dapm_widget *sink = NULL, *next_sink = NULL; 9248724ff17SJeeja KP struct skl_module_cfg *sink_mconfig; 9258724ff17SJeeja KP int ret; 926d93f8e55SVinod Koul 9278724ff17SJeeja KP snd_soc_dapm_widget_for_each_sink_path(w, p) { 928d93f8e55SVinod Koul if (!p->connect) 929d93f8e55SVinod Koul continue; 930d93f8e55SVinod Koul 931bcc2a2dcSCezary Rojewski dev_dbg(skl->dev, 932bcc2a2dcSCezary Rojewski "%s: src widget=%s\n", __func__, w->name); 933bcc2a2dcSCezary Rojewski dev_dbg(skl->dev, 934bcc2a2dcSCezary Rojewski "%s: sink widget=%s\n", __func__, p->sink->name); 935d93f8e55SVinod Koul 9360ed95d76SJeeja KP next_sink = p->sink; 9376bd4cf85SJeeja KP 938bcc2a2dcSCezary Rojewski if (!is_skl_dsp_widget_type(p->sink, skl->dev)) 9396bd4cf85SJeeja KP return skl_tplg_bind_sinks(p->sink, skl, src_w, src_mconfig); 9406bd4cf85SJeeja KP 941d93f8e55SVinod Koul /* 942d93f8e55SVinod Koul * here we will check widgets in sink pipelines, so that 943d93f8e55SVinod Koul * can be any widgets type and we are only interested if 944d93f8e55SVinod Koul * they are ones used for SKL so check that first 945d93f8e55SVinod Koul */ 946d93f8e55SVinod Koul if ((p->sink->priv != NULL) && 947bcc2a2dcSCezary Rojewski is_skl_dsp_widget_type(p->sink, skl->dev)) { 948d93f8e55SVinod Koul 949d93f8e55SVinod Koul sink = p->sink; 950d93f8e55SVinod Koul sink_mconfig = sink->priv; 951d93f8e55SVinod Koul 952b8c722ddSJeeja KP /* 953b8c722ddSJeeja KP * Modules other than PGA leaf can be connected 954b8c722ddSJeeja KP * directly or via switch to a module in another 955b8c722ddSJeeja KP * pipeline. EX: reference path 956b8c722ddSJeeja KP * when the path is enabled, the dst module that needs 957b8c722ddSJeeja KP * to be bound may not be initialized. if the module is 958b8c722ddSJeeja KP * not initialized, add these modules in the deferred 959b8c722ddSJeeja KP * bind list and when the dst module is initialised, 960b8c722ddSJeeja KP * bind this module to the dst_module in deferred list. 961b8c722ddSJeeja KP */ 962b8c722ddSJeeja KP if (((src_mconfig->m_state == SKL_MODULE_INIT_DONE) 963b8c722ddSJeeja KP && (sink_mconfig->m_state == SKL_MODULE_UNINIT))) { 964b8c722ddSJeeja KP 965b8c722ddSJeeja KP ret = skl_tplg_module_add_deferred_bind(skl, 966b8c722ddSJeeja KP src_mconfig, sink_mconfig); 967b8c722ddSJeeja KP 968b8c722ddSJeeja KP if (ret < 0) 969b8c722ddSJeeja KP return ret; 970b8c722ddSJeeja KP 971b8c722ddSJeeja KP } 972b8c722ddSJeeja KP 973b8c722ddSJeeja KP 974cc6a4044SJeeja KP if (src_mconfig->m_state == SKL_MODULE_UNINIT || 975cc6a4044SJeeja KP sink_mconfig->m_state == SKL_MODULE_UNINIT) 976cc6a4044SJeeja KP continue; 977cc6a4044SJeeja KP 978d93f8e55SVinod Koul /* Bind source to sink, mixin is always source */ 979bcc2a2dcSCezary Rojewski ret = skl_bind_modules(skl, src_mconfig, sink_mconfig); 980d93f8e55SVinod Koul if (ret) 981d93f8e55SVinod Koul return ret; 982d93f8e55SVinod Koul 983cc6a4044SJeeja KP /* set module params after bind */ 984bcc2a2dcSCezary Rojewski skl_tplg_set_module_bind_params(src_w, 985bcc2a2dcSCezary Rojewski src_mconfig, skl); 986bcc2a2dcSCezary Rojewski skl_tplg_set_module_bind_params(sink, 987bcc2a2dcSCezary Rojewski sink_mconfig, skl); 988cc6a4044SJeeja KP 989d93f8e55SVinod Koul /* Start sinks pipe first */ 990d93f8e55SVinod Koul if (sink_mconfig->pipe->state != SKL_PIPE_STARTED) { 991d1730c3dSJeeja KP if (sink_mconfig->pipe->conn_type != 992d1730c3dSJeeja KP SKL_PIPE_CONN_TYPE_FE) 993bcc2a2dcSCezary Rojewski ret = skl_run_pipe(skl, 994d1730c3dSJeeja KP sink_mconfig->pipe); 995d93f8e55SVinod Koul if (ret) 996d93f8e55SVinod Koul return ret; 997d93f8e55SVinod Koul } 998d93f8e55SVinod Koul } 999d93f8e55SVinod Koul } 1000d93f8e55SVinod Koul 100110a5439fSguneshwor.o.singh@intel.com if (!sink && next_sink) 10026bd4cf85SJeeja KP return skl_tplg_bind_sinks(next_sink, skl, src_w, src_mconfig); 10038724ff17SJeeja KP 10048724ff17SJeeja KP return 0; 10058724ff17SJeeja KP } 10068724ff17SJeeja KP 1007d93f8e55SVinod Koul /* 1008d93f8e55SVinod Koul * A PGA represents a module in a pipeline. So in the Pre-PMU event of PGA 1009d93f8e55SVinod Koul * we need to do following: 1010d93f8e55SVinod Koul * - Bind to sink pipeline 1011d93f8e55SVinod Koul * Since the sink pipes can be running and we don't get mixer event on 1012d93f8e55SVinod Koul * connect for already running mixer, we need to find the sink pipes 1013d93f8e55SVinod Koul * here and bind to them. This way dynamic connect works. 1014d93f8e55SVinod Koul * - Start sink pipeline, if not running 1015d93f8e55SVinod Koul * - Then run current pipe 1016d93f8e55SVinod Koul */ 1017d93f8e55SVinod Koul static int skl_tplg_pga_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w, 1018bcc2a2dcSCezary Rojewski struct skl_dev *skl) 1019d93f8e55SVinod Koul { 10208724ff17SJeeja KP struct skl_module_cfg *src_mconfig; 1021d93f8e55SVinod Koul int ret = 0; 1022d93f8e55SVinod Koul 10238724ff17SJeeja KP src_mconfig = w->priv; 1024d93f8e55SVinod Koul 1025d93f8e55SVinod Koul /* 1026d93f8e55SVinod Koul * find which sink it is connected to, bind with the sink, 1027d93f8e55SVinod Koul * if sink is not started, start sink pipe first, then start 1028d93f8e55SVinod Koul * this pipe 1029d93f8e55SVinod Koul */ 10306bd4cf85SJeeja KP ret = skl_tplg_bind_sinks(w, skl, w, src_mconfig); 10318724ff17SJeeja KP if (ret) 10328724ff17SJeeja KP return ret; 10338724ff17SJeeja KP 1034d93f8e55SVinod Koul /* Start source pipe last after starting all sinks */ 1035d1730c3dSJeeja KP if (src_mconfig->pipe->conn_type != SKL_PIPE_CONN_TYPE_FE) 1036bcc2a2dcSCezary Rojewski return skl_run_pipe(skl, src_mconfig->pipe); 1037d93f8e55SVinod Koul 1038d93f8e55SVinod Koul return 0; 1039d93f8e55SVinod Koul } 1040d93f8e55SVinod Koul 10418724ff17SJeeja KP static struct snd_soc_dapm_widget *skl_get_src_dsp_widget( 1042bcc2a2dcSCezary Rojewski struct snd_soc_dapm_widget *w, struct skl_dev *skl) 10438724ff17SJeeja KP { 10448724ff17SJeeja KP struct snd_soc_dapm_path *p; 10458724ff17SJeeja KP struct snd_soc_dapm_widget *src_w = NULL; 10468724ff17SJeeja KP 1047d93f8e55SVinod Koul snd_soc_dapm_widget_for_each_source_path(w, p) { 10488724ff17SJeeja KP src_w = p->source; 1049d93f8e55SVinod Koul if (!p->connect) 1050d93f8e55SVinod Koul continue; 1051d93f8e55SVinod Koul 1052bcc2a2dcSCezary Rojewski dev_dbg(skl->dev, "sink widget=%s\n", w->name); 1053bcc2a2dcSCezary Rojewski dev_dbg(skl->dev, "src widget=%s\n", p->source->name); 1054d93f8e55SVinod Koul 1055d93f8e55SVinod Koul /* 10568724ff17SJeeja KP * here we will check widgets in sink pipelines, so that can 10578724ff17SJeeja KP * be any widgets type and we are only interested if they are 10588724ff17SJeeja KP * ones used for SKL so check that first 1059d93f8e55SVinod Koul */ 10608724ff17SJeeja KP if ((p->source->priv != NULL) && 1061bcc2a2dcSCezary Rojewski is_skl_dsp_widget_type(p->source, skl->dev)) { 10628724ff17SJeeja KP return p->source; 1063d93f8e55SVinod Koul } 1064d93f8e55SVinod Koul } 1065d93f8e55SVinod Koul 10668724ff17SJeeja KP if (src_w != NULL) 10678724ff17SJeeja KP return skl_get_src_dsp_widget(src_w, skl); 1068d93f8e55SVinod Koul 10698724ff17SJeeja KP return NULL; 1070d93f8e55SVinod Koul } 1071d93f8e55SVinod Koul 1072d93f8e55SVinod Koul /* 1073d93f8e55SVinod Koul * in the Post-PMU event of mixer we need to do following: 1074d93f8e55SVinod Koul * - Check if this pipe is running 1075d93f8e55SVinod Koul * - if not, then 1076d93f8e55SVinod Koul * - bind this pipeline to its source pipeline 1077d93f8e55SVinod Koul * if source pipe is already running, this means it is a dynamic 1078d93f8e55SVinod Koul * connection and we need to bind only to that pipe 1079d93f8e55SVinod Koul * - start this pipeline 1080d93f8e55SVinod Koul */ 1081d93f8e55SVinod Koul static int skl_tplg_mixer_dapm_post_pmu_event(struct snd_soc_dapm_widget *w, 1082bcc2a2dcSCezary Rojewski struct skl_dev *skl) 1083d93f8e55SVinod Koul { 1084d93f8e55SVinod Koul int ret = 0; 1085d93f8e55SVinod Koul struct snd_soc_dapm_widget *source, *sink; 1086d93f8e55SVinod Koul struct skl_module_cfg *src_mconfig, *sink_mconfig; 1087d93f8e55SVinod Koul int src_pipe_started = 0; 1088d93f8e55SVinod Koul 1089d93f8e55SVinod Koul sink = w; 1090d93f8e55SVinod Koul sink_mconfig = sink->priv; 1091d93f8e55SVinod Koul 1092d93f8e55SVinod Koul /* 1093d93f8e55SVinod Koul * If source pipe is already started, that means source is driving 1094d93f8e55SVinod Koul * one more sink before this sink got connected, Since source is 1095d93f8e55SVinod Koul * started, bind this sink to source and start this pipe. 1096d93f8e55SVinod Koul */ 10978724ff17SJeeja KP source = skl_get_src_dsp_widget(w, skl); 10988724ff17SJeeja KP if (source != NULL) { 1099d93f8e55SVinod Koul src_mconfig = source->priv; 1100d93f8e55SVinod Koul sink_mconfig = sink->priv; 1101d93f8e55SVinod Koul src_pipe_started = 1; 1102d93f8e55SVinod Koul 1103d93f8e55SVinod Koul /* 11048724ff17SJeeja KP * check pipe state, then no need to bind or start the 11058724ff17SJeeja KP * pipe 1106d93f8e55SVinod Koul */ 1107d93f8e55SVinod Koul if (src_mconfig->pipe->state != SKL_PIPE_STARTED) 1108d93f8e55SVinod Koul src_pipe_started = 0; 1109d93f8e55SVinod Koul } 1110d93f8e55SVinod Koul 1111d93f8e55SVinod Koul if (src_pipe_started) { 1112bcc2a2dcSCezary Rojewski ret = skl_bind_modules(skl, src_mconfig, sink_mconfig); 1113d93f8e55SVinod Koul if (ret) 1114d93f8e55SVinod Koul return ret; 1115d93f8e55SVinod Koul 1116cc6a4044SJeeja KP /* set module params after bind */ 1117bcc2a2dcSCezary Rojewski skl_tplg_set_module_bind_params(source, src_mconfig, skl); 1118bcc2a2dcSCezary Rojewski skl_tplg_set_module_bind_params(sink, sink_mconfig, skl); 1119cc6a4044SJeeja KP 1120d1730c3dSJeeja KP if (sink_mconfig->pipe->conn_type != SKL_PIPE_CONN_TYPE_FE) 1121bcc2a2dcSCezary Rojewski ret = skl_run_pipe(skl, sink_mconfig->pipe); 1122d93f8e55SVinod Koul } 1123d93f8e55SVinod Koul 1124d93f8e55SVinod Koul return ret; 1125d93f8e55SVinod Koul } 1126d93f8e55SVinod Koul 1127d93f8e55SVinod Koul /* 1128d93f8e55SVinod Koul * in the Pre-PMD event of mixer we need to do following: 1129d93f8e55SVinod Koul * - Stop the pipe 1130d93f8e55SVinod Koul * - find the source connections and remove that from dapm_path_list 1131d93f8e55SVinod Koul * - unbind with source pipelines if still connected 1132d93f8e55SVinod Koul */ 1133d93f8e55SVinod Koul static int skl_tplg_mixer_dapm_pre_pmd_event(struct snd_soc_dapm_widget *w, 1134bcc2a2dcSCezary Rojewski struct skl_dev *skl) 1135d93f8e55SVinod Koul { 1136d93f8e55SVinod Koul struct skl_module_cfg *src_mconfig, *sink_mconfig; 1137ce1b5551SJeeja KP int ret = 0, i; 1138d93f8e55SVinod Koul 1139ce1b5551SJeeja KP sink_mconfig = w->priv; 1140d93f8e55SVinod Koul 1141d93f8e55SVinod Koul /* Stop the pipe */ 1142bcc2a2dcSCezary Rojewski ret = skl_stop_pipe(skl, sink_mconfig->pipe); 1143d93f8e55SVinod Koul if (ret) 1144d93f8e55SVinod Koul return ret; 1145d93f8e55SVinod Koul 1146f6fa56e2SRamesh Babu for (i = 0; i < sink_mconfig->module->max_input_pins; i++) { 1147ce1b5551SJeeja KP if (sink_mconfig->m_in_pin[i].pin_state == SKL_PIN_BIND_DONE) { 1148ce1b5551SJeeja KP src_mconfig = sink_mconfig->m_in_pin[i].tgt_mcfg; 1149ce1b5551SJeeja KP if (!src_mconfig) 1150ce1b5551SJeeja KP continue; 1151d93f8e55SVinod Koul 1152bcc2a2dcSCezary Rojewski ret = skl_unbind_modules(skl, 1153ce1b5551SJeeja KP src_mconfig, sink_mconfig); 1154ce1b5551SJeeja KP } 1155d93f8e55SVinod Koul } 1156d93f8e55SVinod Koul 1157d93f8e55SVinod Koul return ret; 1158d93f8e55SVinod Koul } 1159d93f8e55SVinod Koul 1160d93f8e55SVinod Koul /* 1161d93f8e55SVinod Koul * in the Post-PMD event of mixer we need to do following: 1162d93f8e55SVinod Koul * - Unbind the modules within the pipeline 1163d93f8e55SVinod Koul * - Delete the pipeline (modules are not required to be explicitly 1164d93f8e55SVinod Koul * deleted, pipeline delete is enough here 1165d93f8e55SVinod Koul */ 1166d93f8e55SVinod Koul static int skl_tplg_mixer_dapm_post_pmd_event(struct snd_soc_dapm_widget *w, 1167bcc2a2dcSCezary Rojewski struct skl_dev *skl) 1168d93f8e55SVinod Koul { 1169d93f8e55SVinod Koul struct skl_module_cfg *mconfig = w->priv; 1170d93f8e55SVinod Koul struct skl_pipe_module *w_module; 1171d93f8e55SVinod Koul struct skl_module_cfg *src_module = NULL, *dst_module; 1172d93f8e55SVinod Koul struct skl_pipe *s_pipe = mconfig->pipe; 1173550b349aSDan Carpenter struct skl_module_deferred_bind *modules, *tmp; 1174d93f8e55SVinod Koul 1175260eb73aSDharageswari R if (s_pipe->state == SKL_PIPE_INVALID) 1176260eb73aSDharageswari R return -EINVAL; 1177260eb73aSDharageswari R 1178d93f8e55SVinod Koul list_for_each_entry(w_module, &s_pipe->w_list, node) { 1179b8c722ddSJeeja KP if (list_empty(&skl->bind_list)) 1180b8c722ddSJeeja KP break; 1181b8c722ddSJeeja KP 1182b8c722ddSJeeja KP src_module = w_module->w->priv; 1183b8c722ddSJeeja KP 1184550b349aSDan Carpenter list_for_each_entry_safe(modules, tmp, &skl->bind_list, node) { 1185b8c722ddSJeeja KP /* 1186b8c722ddSJeeja KP * When the destination module is deleted, Unbind the 1187b8c722ddSJeeja KP * modules from deferred bind list. 1188b8c722ddSJeeja KP */ 1189b8c722ddSJeeja KP if (modules->dst == src_module) { 1190bcc2a2dcSCezary Rojewski skl_unbind_modules(skl, modules->src, 1191b8c722ddSJeeja KP modules->dst); 1192b8c722ddSJeeja KP } 1193b8c722ddSJeeja KP 1194b8c722ddSJeeja KP /* 1195b8c722ddSJeeja KP * When the source module is deleted, remove this entry 1196b8c722ddSJeeja KP * from the deferred bind list. 1197b8c722ddSJeeja KP */ 1198b8c722ddSJeeja KP if (modules->src == src_module) { 1199b8c722ddSJeeja KP list_del(&modules->node); 1200b8c722ddSJeeja KP modules->src = NULL; 1201b8c722ddSJeeja KP modules->dst = NULL; 1202b8c722ddSJeeja KP kfree(modules); 1203b8c722ddSJeeja KP } 1204b8c722ddSJeeja KP } 1205b8c722ddSJeeja KP } 1206b8c722ddSJeeja KP 1207b8c722ddSJeeja KP list_for_each_entry(w_module, &s_pipe->w_list, node) { 1208d93f8e55SVinod Koul dst_module = w_module->w->priv; 1209d93f8e55SVinod Koul 1210d93f8e55SVinod Koul if (src_module == NULL) { 1211d93f8e55SVinod Koul src_module = dst_module; 1212d93f8e55SVinod Koul continue; 1213d93f8e55SVinod Koul } 1214d93f8e55SVinod Koul 1215bcc2a2dcSCezary Rojewski skl_unbind_modules(skl, src_module, dst_module); 1216d93f8e55SVinod Koul src_module = dst_module; 1217d93f8e55SVinod Koul } 1218d93f8e55SVinod Koul 1219bcc2a2dcSCezary Rojewski skl_delete_pipe(skl, mconfig->pipe); 1220d93f8e55SVinod Koul 1221473a4d51SJeeja KP list_for_each_entry(w_module, &s_pipe->w_list, node) { 1222473a4d51SJeeja KP src_module = w_module->w->priv; 1223473a4d51SJeeja KP src_module->m_state = SKL_MODULE_UNINIT; 1224473a4d51SJeeja KP } 1225473a4d51SJeeja KP 1226bcc2a2dcSCezary Rojewski return skl_tplg_unload_pipe_modules(skl, s_pipe); 1227d93f8e55SVinod Koul } 1228d93f8e55SVinod Koul 1229d93f8e55SVinod Koul /* 1230d93f8e55SVinod Koul * in the Post-PMD event of PGA we need to do following: 1231d93f8e55SVinod Koul * - Stop the pipeline 1232d93f8e55SVinod Koul * - In source pipe is connected, unbind with source pipelines 1233d93f8e55SVinod Koul */ 1234d93f8e55SVinod Koul static int skl_tplg_pga_dapm_post_pmd_event(struct snd_soc_dapm_widget *w, 1235bcc2a2dcSCezary Rojewski struct skl_dev *skl) 1236d93f8e55SVinod Koul { 1237d93f8e55SVinod Koul struct skl_module_cfg *src_mconfig, *sink_mconfig; 1238ce1b5551SJeeja KP int ret = 0, i; 1239d93f8e55SVinod Koul 1240ce1b5551SJeeja KP src_mconfig = w->priv; 1241d93f8e55SVinod Koul 1242d93f8e55SVinod Koul /* Stop the pipe since this is a mixin module */ 1243bcc2a2dcSCezary Rojewski ret = skl_stop_pipe(skl, src_mconfig->pipe); 1244d93f8e55SVinod Koul if (ret) 1245d93f8e55SVinod Koul return ret; 1246d93f8e55SVinod Koul 1247f6fa56e2SRamesh Babu for (i = 0; i < src_mconfig->module->max_output_pins; i++) { 1248ce1b5551SJeeja KP if (src_mconfig->m_out_pin[i].pin_state == SKL_PIN_BIND_DONE) { 1249ce1b5551SJeeja KP sink_mconfig = src_mconfig->m_out_pin[i].tgt_mcfg; 1250ce1b5551SJeeja KP if (!sink_mconfig) 1251ce1b5551SJeeja KP continue; 1252d93f8e55SVinod Koul /* 1253ce1b5551SJeeja KP * This is a connecter and if path is found that means 1254d93f8e55SVinod Koul * unbind between source and sink has not happened yet 1255d93f8e55SVinod Koul */ 1256bcc2a2dcSCezary Rojewski ret = skl_unbind_modules(skl, src_mconfig, 1257ce1b5551SJeeja KP sink_mconfig); 1258ce1b5551SJeeja KP } 1259d93f8e55SVinod Koul } 1260d93f8e55SVinod Koul 1261d93f8e55SVinod Koul return ret; 1262d93f8e55SVinod Koul } 1263d93f8e55SVinod Koul 1264d93f8e55SVinod Koul /* 1265d93f8e55SVinod Koul * In modelling, we assume there will be ONLY one mixer in a pipeline. If a 1266d93f8e55SVinod Koul * second one is required that is created as another pipe entity. 1267d93f8e55SVinod Koul * The mixer is responsible for pipe management and represent a pipeline 1268d93f8e55SVinod Koul * instance 1269d93f8e55SVinod Koul */ 1270d93f8e55SVinod Koul static int skl_tplg_mixer_event(struct snd_soc_dapm_widget *w, 1271d93f8e55SVinod Koul struct snd_kcontrol *k, int event) 1272d93f8e55SVinod Koul { 1273d93f8e55SVinod Koul struct snd_soc_dapm_context *dapm = w->dapm; 1274bcc2a2dcSCezary Rojewski struct skl_dev *skl = get_skl_ctx(dapm->dev); 1275d93f8e55SVinod Koul 1276d93f8e55SVinod Koul switch (event) { 1277d93f8e55SVinod Koul case SND_SOC_DAPM_PRE_PMU: 1278d93f8e55SVinod Koul return skl_tplg_mixer_dapm_pre_pmu_event(w, skl); 1279d93f8e55SVinod Koul 1280d93f8e55SVinod Koul case SND_SOC_DAPM_POST_PMU: 1281d93f8e55SVinod Koul return skl_tplg_mixer_dapm_post_pmu_event(w, skl); 1282d93f8e55SVinod Koul 1283d93f8e55SVinod Koul case SND_SOC_DAPM_PRE_PMD: 1284d93f8e55SVinod Koul return skl_tplg_mixer_dapm_pre_pmd_event(w, skl); 1285d93f8e55SVinod Koul 1286d93f8e55SVinod Koul case SND_SOC_DAPM_POST_PMD: 1287d93f8e55SVinod Koul return skl_tplg_mixer_dapm_post_pmd_event(w, skl); 1288d93f8e55SVinod Koul } 1289d93f8e55SVinod Koul 1290d93f8e55SVinod Koul return 0; 1291d93f8e55SVinod Koul } 1292d93f8e55SVinod Koul 1293d93f8e55SVinod Koul /* 1294d93f8e55SVinod Koul * In modelling, we assumed rest of the modules in pipeline are PGA. But we 1295d93f8e55SVinod Koul * are interested in last PGA (leaf PGA) in a pipeline to disconnect with 1296d93f8e55SVinod Koul * the sink when it is running (two FE to one BE or one FE to two BE) 1297d93f8e55SVinod Koul * scenarios 1298d93f8e55SVinod Koul */ 1299d93f8e55SVinod Koul static int skl_tplg_pga_event(struct snd_soc_dapm_widget *w, 1300d93f8e55SVinod Koul struct snd_kcontrol *k, int event) 1301d93f8e55SVinod Koul 1302d93f8e55SVinod Koul { 1303d93f8e55SVinod Koul struct snd_soc_dapm_context *dapm = w->dapm; 1304bcc2a2dcSCezary Rojewski struct skl_dev *skl = get_skl_ctx(dapm->dev); 1305d93f8e55SVinod Koul 1306d93f8e55SVinod Koul switch (event) { 1307d93f8e55SVinod Koul case SND_SOC_DAPM_PRE_PMU: 1308d93f8e55SVinod Koul return skl_tplg_pga_dapm_pre_pmu_event(w, skl); 1309d93f8e55SVinod Koul 1310d93f8e55SVinod Koul case SND_SOC_DAPM_POST_PMD: 1311d93f8e55SVinod Koul return skl_tplg_pga_dapm_post_pmd_event(w, skl); 1312d93f8e55SVinod Koul } 1313d93f8e55SVinod Koul 1314d93f8e55SVinod Koul return 0; 1315d93f8e55SVinod Koul } 1316cfb0a873SVinod Koul 1317140adfbaSJeeja KP static int skl_tplg_tlv_control_get(struct snd_kcontrol *kcontrol, 1318140adfbaSJeeja KP unsigned int __user *data, unsigned int size) 1319140adfbaSJeeja KP { 1320140adfbaSJeeja KP struct soc_bytes_ext *sb = 1321140adfbaSJeeja KP (struct soc_bytes_ext *)kcontrol->private_value; 1322140adfbaSJeeja KP struct skl_algo_data *bc = (struct skl_algo_data *)sb->dobj.private; 13237d9f2911SOmair M Abdullah struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol); 13247d9f2911SOmair M Abdullah struct skl_module_cfg *mconfig = w->priv; 1325bcc2a2dcSCezary Rojewski struct skl_dev *skl = get_skl_ctx(w->dapm->dev); 13267d9f2911SOmair M Abdullah 13277d9f2911SOmair M Abdullah if (w->power) 1328bcc2a2dcSCezary Rojewski skl_get_module_params(skl, (u32 *)bc->params, 13290d682104SDharageswari R bc->size, bc->param_id, mconfig); 1330140adfbaSJeeja KP 133141556f68SVinod Koul /* decrement size for TLV header */ 133241556f68SVinod Koul size -= 2 * sizeof(u32); 133341556f68SVinod Koul 133441556f68SVinod Koul /* check size as we don't want to send kernel data */ 133541556f68SVinod Koul if (size > bc->max) 133641556f68SVinod Koul size = bc->max; 133741556f68SVinod Koul 1338140adfbaSJeeja KP if (bc->params) { 1339140adfbaSJeeja KP if (copy_to_user(data, &bc->param_id, sizeof(u32))) 1340140adfbaSJeeja KP return -EFAULT; 1341e8bc3c99SDan Carpenter if (copy_to_user(data + 1, &size, sizeof(u32))) 1342140adfbaSJeeja KP return -EFAULT; 1343e8bc3c99SDan Carpenter if (copy_to_user(data + 2, bc->params, size)) 1344140adfbaSJeeja KP return -EFAULT; 1345140adfbaSJeeja KP } 1346140adfbaSJeeja KP 1347140adfbaSJeeja KP return 0; 1348140adfbaSJeeja KP } 1349140adfbaSJeeja KP 1350140adfbaSJeeja KP #define SKL_PARAM_VENDOR_ID 0xff 1351140adfbaSJeeja KP 1352140adfbaSJeeja KP static int skl_tplg_tlv_control_set(struct snd_kcontrol *kcontrol, 1353140adfbaSJeeja KP const unsigned int __user *data, unsigned int size) 1354140adfbaSJeeja KP { 1355140adfbaSJeeja KP struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol); 1356140adfbaSJeeja KP struct skl_module_cfg *mconfig = w->priv; 1357140adfbaSJeeja KP struct soc_bytes_ext *sb = 1358140adfbaSJeeja KP (struct soc_bytes_ext *)kcontrol->private_value; 1359140adfbaSJeeja KP struct skl_algo_data *ac = (struct skl_algo_data *)sb->dobj.private; 1360bcc2a2dcSCezary Rojewski struct skl_dev *skl = get_skl_ctx(w->dapm->dev); 1361140adfbaSJeeja KP 1362140adfbaSJeeja KP if (ac->params) { 1363a8cd7066SKamil Lulko /* 1364a8cd7066SKamil Lulko * Widget data is expected to be stripped of T and L 1365a8cd7066SKamil Lulko */ 1366a8cd7066SKamil Lulko size -= 2 * sizeof(unsigned int); 1367a8cd7066SKamil Lulko data += 2; 1368a8cd7066SKamil Lulko 13690d682104SDharageswari R if (size > ac->max) 13700d682104SDharageswari R return -EINVAL; 13710d682104SDharageswari R ac->size = size; 1372a8cd7066SKamil Lulko 1373140adfbaSJeeja KP if (copy_from_user(ac->params, data, size)) 1374140adfbaSJeeja KP return -EFAULT; 1375140adfbaSJeeja KP 1376140adfbaSJeeja KP if (w->power) 1377bcc2a2dcSCezary Rojewski return skl_set_module_params(skl, 13780d682104SDharageswari R (u32 *)ac->params, ac->size, 1379140adfbaSJeeja KP ac->param_id, mconfig); 1380140adfbaSJeeja KP } 1381140adfbaSJeeja KP 1382140adfbaSJeeja KP return 0; 1383140adfbaSJeeja KP } 1384140adfbaSJeeja KP 13857a1b749bSDharageswari R static int skl_tplg_mic_control_get(struct snd_kcontrol *kcontrol, 13867a1b749bSDharageswari R struct snd_ctl_elem_value *ucontrol) 13877a1b749bSDharageswari R { 13887a1b749bSDharageswari R struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol); 13897a1b749bSDharageswari R struct skl_module_cfg *mconfig = w->priv; 13907a1b749bSDharageswari R struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; 13917a1b749bSDharageswari R u32 ch_type = *((u32 *)ec->dobj.private); 13927a1b749bSDharageswari R 13937a1b749bSDharageswari R if (mconfig->dmic_ch_type == ch_type) 13947a1b749bSDharageswari R ucontrol->value.enumerated.item[0] = 13957a1b749bSDharageswari R mconfig->dmic_ch_combo_index; 13967a1b749bSDharageswari R else 13977a1b749bSDharageswari R ucontrol->value.enumerated.item[0] = 0; 13987a1b749bSDharageswari R 13997a1b749bSDharageswari R return 0; 14007a1b749bSDharageswari R } 14017a1b749bSDharageswari R 14027a1b749bSDharageswari R static int skl_fill_mic_sel_params(struct skl_module_cfg *mconfig, 14037a1b749bSDharageswari R struct skl_mic_sel_config *mic_cfg, struct device *dev) 14047a1b749bSDharageswari R { 14057a1b749bSDharageswari R struct skl_specific_cfg *sp_cfg = &mconfig->formats_config; 14067a1b749bSDharageswari R 14077a1b749bSDharageswari R sp_cfg->caps_size = sizeof(struct skl_mic_sel_config); 14087a1b749bSDharageswari R sp_cfg->set_params = SKL_PARAM_SET; 14097a1b749bSDharageswari R sp_cfg->param_id = 0x00; 14107a1b749bSDharageswari R if (!sp_cfg->caps) { 14117a1b749bSDharageswari R sp_cfg->caps = devm_kzalloc(dev, sp_cfg->caps_size, GFP_KERNEL); 14127a1b749bSDharageswari R if (!sp_cfg->caps) 14137a1b749bSDharageswari R return -ENOMEM; 14147a1b749bSDharageswari R } 14157a1b749bSDharageswari R 14167a1b749bSDharageswari R mic_cfg->mic_switch = SKL_MIC_SEL_SWITCH; 14177a1b749bSDharageswari R mic_cfg->flags = 0; 14187a1b749bSDharageswari R memcpy(sp_cfg->caps, mic_cfg, sp_cfg->caps_size); 14197a1b749bSDharageswari R 14207a1b749bSDharageswari R return 0; 14217a1b749bSDharageswari R } 14227a1b749bSDharageswari R 14237a1b749bSDharageswari R static int skl_tplg_mic_control_set(struct snd_kcontrol *kcontrol, 14247a1b749bSDharageswari R struct snd_ctl_elem_value *ucontrol) 14257a1b749bSDharageswari R { 14267a1b749bSDharageswari R struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol); 14277a1b749bSDharageswari R struct skl_module_cfg *mconfig = w->priv; 14287a1b749bSDharageswari R struct skl_mic_sel_config mic_cfg = {0}; 14297a1b749bSDharageswari R struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; 14307a1b749bSDharageswari R u32 ch_type = *((u32 *)ec->dobj.private); 14317a1b749bSDharageswari R const int *list; 14327a1b749bSDharageswari R u8 in_ch, out_ch, index; 14337a1b749bSDharageswari R 14347a1b749bSDharageswari R mconfig->dmic_ch_type = ch_type; 14357a1b749bSDharageswari R mconfig->dmic_ch_combo_index = ucontrol->value.enumerated.item[0]; 14367a1b749bSDharageswari R 14377a1b749bSDharageswari R /* enum control index 0 is INVALID, so no channels to be set */ 14387a1b749bSDharageswari R if (mconfig->dmic_ch_combo_index == 0) 14397a1b749bSDharageswari R return 0; 14407a1b749bSDharageswari R 14417a1b749bSDharageswari R /* No valid channel selection map for index 0, so offset by 1 */ 14427a1b749bSDharageswari R index = mconfig->dmic_ch_combo_index - 1; 14437a1b749bSDharageswari R 14447a1b749bSDharageswari R switch (ch_type) { 14457a1b749bSDharageswari R case SKL_CH_MONO: 14467a1b749bSDharageswari R if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_mono_list)) 14477a1b749bSDharageswari R return -EINVAL; 14487a1b749bSDharageswari R 14497a1b749bSDharageswari R list = &mic_mono_list[index]; 14507a1b749bSDharageswari R break; 14517a1b749bSDharageswari R 14527a1b749bSDharageswari R case SKL_CH_STEREO: 14537a1b749bSDharageswari R if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_stereo_list)) 14547a1b749bSDharageswari R return -EINVAL; 14557a1b749bSDharageswari R 14567a1b749bSDharageswari R list = mic_stereo_list[index]; 14577a1b749bSDharageswari R break; 14587a1b749bSDharageswari R 14597a1b749bSDharageswari R case SKL_CH_TRIO: 14607a1b749bSDharageswari R if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_trio_list)) 14617a1b749bSDharageswari R return -EINVAL; 14627a1b749bSDharageswari R 14637a1b749bSDharageswari R list = mic_trio_list[index]; 14647a1b749bSDharageswari R break; 14657a1b749bSDharageswari R 14667a1b749bSDharageswari R case SKL_CH_QUATRO: 14677a1b749bSDharageswari R if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_quatro_list)) 14687a1b749bSDharageswari R return -EINVAL; 14697a1b749bSDharageswari R 14707a1b749bSDharageswari R list = mic_quatro_list[index]; 14717a1b749bSDharageswari R break; 14727a1b749bSDharageswari R 14737a1b749bSDharageswari R default: 14747a1b749bSDharageswari R dev_err(w->dapm->dev, 14757a1b749bSDharageswari R "Invalid channel %d for mic_select module\n", 14767a1b749bSDharageswari R ch_type); 14777a1b749bSDharageswari R return -EINVAL; 14787a1b749bSDharageswari R 14797a1b749bSDharageswari R } 14807a1b749bSDharageswari R 14817a1b749bSDharageswari R /* channel type enum map to number of chanels for that type */ 14827a1b749bSDharageswari R for (out_ch = 0; out_ch < ch_type; out_ch++) { 14837a1b749bSDharageswari R in_ch = list[out_ch]; 14847a1b749bSDharageswari R mic_cfg.blob[out_ch][in_ch] = SKL_DEFAULT_MIC_SEL_GAIN; 14857a1b749bSDharageswari R } 14867a1b749bSDharageswari R 14877a1b749bSDharageswari R return skl_fill_mic_sel_params(mconfig, &mic_cfg, w->dapm->dev); 14887a1b749bSDharageswari R } 14897a1b749bSDharageswari R 1490cfb0a873SVinod Koul /* 14918871dcb9SJeeja KP * Fill the dma id for host and link. In case of passthrough 14928871dcb9SJeeja KP * pipeline, this will both host and link in the same 14938871dcb9SJeeja KP * pipeline, so need to copy the link and host based on dev_type 14948871dcb9SJeeja KP */ 14958871dcb9SJeeja KP static void skl_tplg_fill_dma_id(struct skl_module_cfg *mcfg, 14968871dcb9SJeeja KP struct skl_pipe_params *params) 14978871dcb9SJeeja KP { 14988871dcb9SJeeja KP struct skl_pipe *pipe = mcfg->pipe; 14998871dcb9SJeeja KP 15008871dcb9SJeeja KP if (pipe->passthru) { 15018871dcb9SJeeja KP switch (mcfg->dev_type) { 15028871dcb9SJeeja KP case SKL_DEVICE_HDALINK: 15038871dcb9SJeeja KP pipe->p_params->link_dma_id = params->link_dma_id; 150412c3be0eSJeeja KP pipe->p_params->link_index = params->link_index; 15057f975a38SJeeja KP pipe->p_params->link_bps = params->link_bps; 15068871dcb9SJeeja KP break; 15078871dcb9SJeeja KP 15088871dcb9SJeeja KP case SKL_DEVICE_HDAHOST: 15098871dcb9SJeeja KP pipe->p_params->host_dma_id = params->host_dma_id; 15107f975a38SJeeja KP pipe->p_params->host_bps = params->host_bps; 15118871dcb9SJeeja KP break; 15128871dcb9SJeeja KP 15138871dcb9SJeeja KP default: 15148871dcb9SJeeja KP break; 15158871dcb9SJeeja KP } 15168871dcb9SJeeja KP pipe->p_params->s_fmt = params->s_fmt; 15178871dcb9SJeeja KP pipe->p_params->ch = params->ch; 15188871dcb9SJeeja KP pipe->p_params->s_freq = params->s_freq; 15198871dcb9SJeeja KP pipe->p_params->stream = params->stream; 152012c3be0eSJeeja KP pipe->p_params->format = params->format; 15218871dcb9SJeeja KP 15228871dcb9SJeeja KP } else { 15238871dcb9SJeeja KP memcpy(pipe->p_params, params, sizeof(*params)); 15248871dcb9SJeeja KP } 15258871dcb9SJeeja KP } 15268871dcb9SJeeja KP 15278871dcb9SJeeja KP /* 1528cfb0a873SVinod Koul * The FE params are passed by hw_params of the DAI. 1529cfb0a873SVinod Koul * On hw_params, the params are stored in Gateway module of the FE and we 1530cfb0a873SVinod Koul * need to calculate the format in DSP module configuration, that 1531cfb0a873SVinod Koul * conversion is done here 1532cfb0a873SVinod Koul */ 1533cfb0a873SVinod Koul int skl_tplg_update_pipe_params(struct device *dev, 1534cfb0a873SVinod Koul struct skl_module_cfg *mconfig, 1535cfb0a873SVinod Koul struct skl_pipe_params *params) 1536cfb0a873SVinod Koul { 1537f6fa56e2SRamesh Babu struct skl_module_res *res = &mconfig->module->resources[0]; 1538bcc2a2dcSCezary Rojewski struct skl_dev *skl = get_skl_ctx(dev); 1539cfb0a873SVinod Koul struct skl_module_fmt *format = NULL; 1540f6fa56e2SRamesh Babu u8 cfg_idx = mconfig->pipe->cur_config_idx; 1541cfb0a873SVinod Koul 15428871dcb9SJeeja KP skl_tplg_fill_dma_id(mconfig, params); 1543f6fa56e2SRamesh Babu mconfig->fmt_idx = mconfig->mod_cfg[cfg_idx].fmt_idx; 1544f6fa56e2SRamesh Babu mconfig->res_idx = mconfig->mod_cfg[cfg_idx].res_idx; 1545f6fa56e2SRamesh Babu 1546f6fa56e2SRamesh Babu if (skl->nr_modules) 1547f6fa56e2SRamesh Babu return 0; 1548cfb0a873SVinod Koul 1549cfb0a873SVinod Koul if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) 1550f6fa56e2SRamesh Babu format = &mconfig->module->formats[0].inputs[0].fmt; 1551cfb0a873SVinod Koul else 1552f6fa56e2SRamesh Babu format = &mconfig->module->formats[0].outputs[0].fmt; 1553cfb0a873SVinod Koul 1554cfb0a873SVinod Koul /* set the hw_params */ 1555cfb0a873SVinod Koul format->s_freq = params->s_freq; 1556cfb0a873SVinod Koul format->channels = params->ch; 1557cfb0a873SVinod Koul format->valid_bit_depth = skl_get_bit_depth(params->s_fmt); 1558cfb0a873SVinod Koul 1559cfb0a873SVinod Koul /* 1560cfb0a873SVinod Koul * 16 bit is 16 bit container whereas 24 bit is in 32 bit 1561cfb0a873SVinod Koul * container so update bit depth accordingly 1562cfb0a873SVinod Koul */ 1563cfb0a873SVinod Koul switch (format->valid_bit_depth) { 1564cfb0a873SVinod Koul case SKL_DEPTH_16BIT: 1565cfb0a873SVinod Koul format->bit_depth = format->valid_bit_depth; 1566cfb0a873SVinod Koul break; 1567cfb0a873SVinod Koul 1568cfb0a873SVinod Koul case SKL_DEPTH_24BIT: 15696654f39eSJeeja KP case SKL_DEPTH_32BIT: 1570cfb0a873SVinod Koul format->bit_depth = SKL_DEPTH_32BIT; 1571cfb0a873SVinod Koul break; 1572cfb0a873SVinod Koul 1573cfb0a873SVinod Koul default: 1574cfb0a873SVinod Koul dev_err(dev, "Invalid bit depth %x for pipe\n", 1575cfb0a873SVinod Koul format->valid_bit_depth); 1576cfb0a873SVinod Koul return -EINVAL; 1577cfb0a873SVinod Koul } 1578cfb0a873SVinod Koul 1579cfb0a873SVinod Koul if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) { 1580f6fa56e2SRamesh Babu res->ibs = (format->s_freq / 1000) * 1581cfb0a873SVinod Koul (format->channels) * 1582cfb0a873SVinod Koul (format->bit_depth >> 3); 1583cfb0a873SVinod Koul } else { 1584f6fa56e2SRamesh Babu res->obs = (format->s_freq / 1000) * 1585cfb0a873SVinod Koul (format->channels) * 1586cfb0a873SVinod Koul (format->bit_depth >> 3); 1587cfb0a873SVinod Koul } 1588cfb0a873SVinod Koul 1589cfb0a873SVinod Koul return 0; 1590cfb0a873SVinod Koul } 1591cfb0a873SVinod Koul 1592cfb0a873SVinod Koul /* 1593cfb0a873SVinod Koul * Query the module config for the FE DAI 1594cfb0a873SVinod Koul * This is used to find the hw_params set for that DAI and apply to FE 1595cfb0a873SVinod Koul * pipeline 1596cfb0a873SVinod Koul */ 1597cfb0a873SVinod Koul struct skl_module_cfg * 1598cfb0a873SVinod Koul skl_tplg_fe_get_cpr_module(struct snd_soc_dai *dai, int stream) 1599cfb0a873SVinod Koul { 1600cfb0a873SVinod Koul struct snd_soc_dapm_widget *w; 1601cfb0a873SVinod Koul struct snd_soc_dapm_path *p = NULL; 1602cfb0a873SVinod Koul 1603cfb0a873SVinod Koul if (stream == SNDRV_PCM_STREAM_PLAYBACK) { 1604cfb0a873SVinod Koul w = dai->playback_widget; 1605f0900eb2SSubhransu S. Prusty snd_soc_dapm_widget_for_each_sink_path(w, p) { 1606cfb0a873SVinod Koul if (p->connect && p->sink->power && 1607cb1f904dSGuneshwor Singh !is_skl_dsp_widget_type(p->sink, dai->dev)) 1608cfb0a873SVinod Koul continue; 1609cfb0a873SVinod Koul 1610cfb0a873SVinod Koul if (p->sink->priv) { 1611cfb0a873SVinod Koul dev_dbg(dai->dev, "set params for %s\n", 1612cfb0a873SVinod Koul p->sink->name); 1613cfb0a873SVinod Koul return p->sink->priv; 1614cfb0a873SVinod Koul } 1615cfb0a873SVinod Koul } 1616cfb0a873SVinod Koul } else { 1617cfb0a873SVinod Koul w = dai->capture_widget; 1618f0900eb2SSubhransu S. Prusty snd_soc_dapm_widget_for_each_source_path(w, p) { 1619cfb0a873SVinod Koul if (p->connect && p->source->power && 1620cb1f904dSGuneshwor Singh !is_skl_dsp_widget_type(p->source, dai->dev)) 1621cfb0a873SVinod Koul continue; 1622cfb0a873SVinod Koul 1623cfb0a873SVinod Koul if (p->source->priv) { 1624cfb0a873SVinod Koul dev_dbg(dai->dev, "set params for %s\n", 1625cfb0a873SVinod Koul p->source->name); 1626cfb0a873SVinod Koul return p->source->priv; 1627cfb0a873SVinod Koul } 1628cfb0a873SVinod Koul } 1629cfb0a873SVinod Koul } 1630cfb0a873SVinod Koul 1631cfb0a873SVinod Koul return NULL; 1632cfb0a873SVinod Koul } 1633cfb0a873SVinod Koul 1634718a42b5SDharageswari.R static struct skl_module_cfg *skl_get_mconfig_pb_cpr( 1635718a42b5SDharageswari.R struct snd_soc_dai *dai, struct snd_soc_dapm_widget *w) 1636718a42b5SDharageswari.R { 1637718a42b5SDharageswari.R struct snd_soc_dapm_path *p; 1638718a42b5SDharageswari.R struct skl_module_cfg *mconfig = NULL; 1639718a42b5SDharageswari.R 1640718a42b5SDharageswari.R snd_soc_dapm_widget_for_each_source_path(w, p) { 1641718a42b5SDharageswari.R if (w->endpoints[SND_SOC_DAPM_DIR_OUT] > 0) { 1642718a42b5SDharageswari.R if (p->connect && 1643718a42b5SDharageswari.R (p->sink->id == snd_soc_dapm_aif_out) && 1644718a42b5SDharageswari.R p->source->priv) { 1645718a42b5SDharageswari.R mconfig = p->source->priv; 1646718a42b5SDharageswari.R return mconfig; 1647718a42b5SDharageswari.R } 1648718a42b5SDharageswari.R mconfig = skl_get_mconfig_pb_cpr(dai, p->source); 1649718a42b5SDharageswari.R if (mconfig) 1650718a42b5SDharageswari.R return mconfig; 1651718a42b5SDharageswari.R } 1652718a42b5SDharageswari.R } 1653718a42b5SDharageswari.R return mconfig; 1654718a42b5SDharageswari.R } 1655718a42b5SDharageswari.R 1656718a42b5SDharageswari.R static struct skl_module_cfg *skl_get_mconfig_cap_cpr( 1657718a42b5SDharageswari.R struct snd_soc_dai *dai, struct snd_soc_dapm_widget *w) 1658718a42b5SDharageswari.R { 1659718a42b5SDharageswari.R struct snd_soc_dapm_path *p; 1660718a42b5SDharageswari.R struct skl_module_cfg *mconfig = NULL; 1661718a42b5SDharageswari.R 1662718a42b5SDharageswari.R snd_soc_dapm_widget_for_each_sink_path(w, p) { 1663718a42b5SDharageswari.R if (w->endpoints[SND_SOC_DAPM_DIR_IN] > 0) { 1664718a42b5SDharageswari.R if (p->connect && 1665718a42b5SDharageswari.R (p->source->id == snd_soc_dapm_aif_in) && 1666718a42b5SDharageswari.R p->sink->priv) { 1667718a42b5SDharageswari.R mconfig = p->sink->priv; 1668718a42b5SDharageswari.R return mconfig; 1669718a42b5SDharageswari.R } 1670718a42b5SDharageswari.R mconfig = skl_get_mconfig_cap_cpr(dai, p->sink); 1671718a42b5SDharageswari.R if (mconfig) 1672718a42b5SDharageswari.R return mconfig; 1673718a42b5SDharageswari.R } 1674718a42b5SDharageswari.R } 1675718a42b5SDharageswari.R return mconfig; 1676718a42b5SDharageswari.R } 1677718a42b5SDharageswari.R 1678718a42b5SDharageswari.R struct skl_module_cfg * 1679718a42b5SDharageswari.R skl_tplg_be_get_cpr_module(struct snd_soc_dai *dai, int stream) 1680718a42b5SDharageswari.R { 1681718a42b5SDharageswari.R struct snd_soc_dapm_widget *w; 1682718a42b5SDharageswari.R struct skl_module_cfg *mconfig; 1683718a42b5SDharageswari.R 1684718a42b5SDharageswari.R if (stream == SNDRV_PCM_STREAM_PLAYBACK) { 1685718a42b5SDharageswari.R w = dai->playback_widget; 1686718a42b5SDharageswari.R mconfig = skl_get_mconfig_pb_cpr(dai, w); 1687718a42b5SDharageswari.R } else { 1688718a42b5SDharageswari.R w = dai->capture_widget; 1689718a42b5SDharageswari.R mconfig = skl_get_mconfig_cap_cpr(dai, w); 1690718a42b5SDharageswari.R } 1691718a42b5SDharageswari.R return mconfig; 1692718a42b5SDharageswari.R } 1693718a42b5SDharageswari.R 1694cfb0a873SVinod Koul static u8 skl_tplg_be_link_type(int dev_type) 1695cfb0a873SVinod Koul { 1696cfb0a873SVinod Koul int ret; 1697cfb0a873SVinod Koul 1698cfb0a873SVinod Koul switch (dev_type) { 1699cfb0a873SVinod Koul case SKL_DEVICE_BT: 1700cfb0a873SVinod Koul ret = NHLT_LINK_SSP; 1701cfb0a873SVinod Koul break; 1702cfb0a873SVinod Koul 1703cfb0a873SVinod Koul case SKL_DEVICE_DMIC: 1704cfb0a873SVinod Koul ret = NHLT_LINK_DMIC; 1705cfb0a873SVinod Koul break; 1706cfb0a873SVinod Koul 1707cfb0a873SVinod Koul case SKL_DEVICE_I2S: 1708cfb0a873SVinod Koul ret = NHLT_LINK_SSP; 1709cfb0a873SVinod Koul break; 1710cfb0a873SVinod Koul 1711cfb0a873SVinod Koul case SKL_DEVICE_HDALINK: 1712cfb0a873SVinod Koul ret = NHLT_LINK_HDA; 1713cfb0a873SVinod Koul break; 1714cfb0a873SVinod Koul 1715cfb0a873SVinod Koul default: 1716cfb0a873SVinod Koul ret = NHLT_LINK_INVALID; 1717cfb0a873SVinod Koul break; 1718cfb0a873SVinod Koul } 1719cfb0a873SVinod Koul 1720cfb0a873SVinod Koul return ret; 1721cfb0a873SVinod Koul } 1722cfb0a873SVinod Koul 1723cfb0a873SVinod Koul /* 1724cfb0a873SVinod Koul * Fill the BE gateway parameters 1725cfb0a873SVinod Koul * The BE gateway expects a blob of parameters which are kept in the ACPI 1726cfb0a873SVinod Koul * NHLT blob, so query the blob for interface type (i2s/pdm) and instance. 1727cfb0a873SVinod Koul * The port can have multiple settings so pick based on the PCM 1728cfb0a873SVinod Koul * parameters 1729cfb0a873SVinod Koul */ 1730cfb0a873SVinod Koul static int skl_tplg_be_fill_pipe_params(struct snd_soc_dai *dai, 1731cfb0a873SVinod Koul struct skl_module_cfg *mconfig, 1732cfb0a873SVinod Koul struct skl_pipe_params *params) 1733cfb0a873SVinod Koul { 1734cfb0a873SVinod Koul struct nhlt_specific_cfg *cfg; 1735bcc2a2dcSCezary Rojewski struct skl_dev *skl = get_skl_ctx(dai->dev); 1736cfb0a873SVinod Koul int link_type = skl_tplg_be_link_type(mconfig->dev_type); 1737db2f586bSSenthilnathan Veppur u8 dev_type = skl_tplg_be_dev_type(mconfig->dev_type); 1738cfb0a873SVinod Koul 17398871dcb9SJeeja KP skl_tplg_fill_dma_id(mconfig, params); 1740cfb0a873SVinod Koul 1741b30c275eSJeeja KP if (link_type == NHLT_LINK_HDA) 1742b30c275eSJeeja KP return 0; 1743b30c275eSJeeja KP 1744cfb0a873SVinod Koul /* update the blob based on virtual bus_id*/ 1745cfb0a873SVinod Koul cfg = skl_get_ep_blob(skl, mconfig->vbus_id, link_type, 1746cfb0a873SVinod Koul params->s_fmt, params->ch, 1747db2f586bSSenthilnathan Veppur params->s_freq, params->stream, 1748db2f586bSSenthilnathan Veppur dev_type); 1749cfb0a873SVinod Koul if (cfg) { 1750cfb0a873SVinod Koul mconfig->formats_config.caps_size = cfg->size; 1751bc03281aSJeeja KP mconfig->formats_config.caps = (u32 *) &cfg->caps; 1752cfb0a873SVinod Koul } else { 1753cfb0a873SVinod Koul dev_err(dai->dev, "Blob NULL for id %x type %d dirn %d\n", 1754cfb0a873SVinod Koul mconfig->vbus_id, link_type, 1755cfb0a873SVinod Koul params->stream); 1756cfb0a873SVinod Koul dev_err(dai->dev, "PCM: ch %d, freq %d, fmt %d\n", 1757cfb0a873SVinod Koul params->ch, params->s_freq, params->s_fmt); 1758cfb0a873SVinod Koul return -EINVAL; 1759cfb0a873SVinod Koul } 1760cfb0a873SVinod Koul 1761cfb0a873SVinod Koul return 0; 1762cfb0a873SVinod Koul } 1763cfb0a873SVinod Koul 1764cfb0a873SVinod Koul static int skl_tplg_be_set_src_pipe_params(struct snd_soc_dai *dai, 1765cfb0a873SVinod Koul struct snd_soc_dapm_widget *w, 1766cfb0a873SVinod Koul struct skl_pipe_params *params) 1767cfb0a873SVinod Koul { 1768cfb0a873SVinod Koul struct snd_soc_dapm_path *p; 17694d8adccbSSubhransu S. Prusty int ret = -EIO; 1770cfb0a873SVinod Koul 1771f0900eb2SSubhransu S. Prusty snd_soc_dapm_widget_for_each_source_path(w, p) { 1772cb1f904dSGuneshwor Singh if (p->connect && is_skl_dsp_widget_type(p->source, dai->dev) && 1773cfb0a873SVinod Koul p->source->priv) { 1774cfb0a873SVinod Koul 17759a03cb49SJeeja KP ret = skl_tplg_be_fill_pipe_params(dai, 17769a03cb49SJeeja KP p->source->priv, params); 17774d8adccbSSubhransu S. Prusty if (ret < 0) 17784d8adccbSSubhransu S. Prusty return ret; 1779cfb0a873SVinod Koul } else { 17809a03cb49SJeeja KP ret = skl_tplg_be_set_src_pipe_params(dai, 17819a03cb49SJeeja KP p->source, params); 17824d8adccbSSubhransu S. Prusty if (ret < 0) 17834d8adccbSSubhransu S. Prusty return ret; 1784cfb0a873SVinod Koul } 1785cfb0a873SVinod Koul } 1786cfb0a873SVinod Koul 17874d8adccbSSubhransu S. Prusty return ret; 1788cfb0a873SVinod Koul } 1789cfb0a873SVinod Koul 1790cfb0a873SVinod Koul static int skl_tplg_be_set_sink_pipe_params(struct snd_soc_dai *dai, 1791cfb0a873SVinod Koul struct snd_soc_dapm_widget *w, struct skl_pipe_params *params) 1792cfb0a873SVinod Koul { 1793cfb0a873SVinod Koul struct snd_soc_dapm_path *p = NULL; 17944d8adccbSSubhransu S. Prusty int ret = -EIO; 1795cfb0a873SVinod Koul 1796f0900eb2SSubhransu S. Prusty snd_soc_dapm_widget_for_each_sink_path(w, p) { 1797cb1f904dSGuneshwor Singh if (p->connect && is_skl_dsp_widget_type(p->sink, dai->dev) && 1798cfb0a873SVinod Koul p->sink->priv) { 1799cfb0a873SVinod Koul 18009a03cb49SJeeja KP ret = skl_tplg_be_fill_pipe_params(dai, 18019a03cb49SJeeja KP p->sink->priv, params); 18024d8adccbSSubhransu S. Prusty if (ret < 0) 18034d8adccbSSubhransu S. Prusty return ret; 18044d8adccbSSubhransu S. Prusty } else { 18054d8adccbSSubhransu S. Prusty ret = skl_tplg_be_set_sink_pipe_params( 1806cfb0a873SVinod Koul dai, p->sink, params); 18074d8adccbSSubhransu S. Prusty if (ret < 0) 18084d8adccbSSubhransu S. Prusty return ret; 1809cfb0a873SVinod Koul } 1810cfb0a873SVinod Koul } 1811cfb0a873SVinod Koul 18124d8adccbSSubhransu S. Prusty return ret; 1813cfb0a873SVinod Koul } 1814cfb0a873SVinod Koul 1815cfb0a873SVinod Koul /* 1816cfb0a873SVinod Koul * BE hw_params can be a source parameters (capture) or sink parameters 1817cfb0a873SVinod Koul * (playback). Based on sink and source we need to either find the source 1818cfb0a873SVinod Koul * list or the sink list and set the pipeline parameters 1819cfb0a873SVinod Koul */ 1820cfb0a873SVinod Koul int skl_tplg_be_update_params(struct snd_soc_dai *dai, 1821cfb0a873SVinod Koul struct skl_pipe_params *params) 1822cfb0a873SVinod Koul { 1823cfb0a873SVinod Koul struct snd_soc_dapm_widget *w; 1824cfb0a873SVinod Koul 1825cfb0a873SVinod Koul if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) { 1826cfb0a873SVinod Koul w = dai->playback_widget; 1827cfb0a873SVinod Koul 1828cfb0a873SVinod Koul return skl_tplg_be_set_src_pipe_params(dai, w, params); 1829cfb0a873SVinod Koul 1830cfb0a873SVinod Koul } else { 1831cfb0a873SVinod Koul w = dai->capture_widget; 1832cfb0a873SVinod Koul 1833cfb0a873SVinod Koul return skl_tplg_be_set_sink_pipe_params(dai, w, params); 1834cfb0a873SVinod Koul } 1835cfb0a873SVinod Koul 1836cfb0a873SVinod Koul return 0; 1837cfb0a873SVinod Koul } 18383af36706SVinod Koul 18393af36706SVinod Koul static const struct snd_soc_tplg_widget_events skl_tplg_widget_ops[] = { 18403af36706SVinod Koul {SKL_MIXER_EVENT, skl_tplg_mixer_event}, 18419a1e3507SVinod Koul {SKL_VMIXER_EVENT, skl_tplg_mixer_event}, 18423af36706SVinod Koul {SKL_PGA_EVENT, skl_tplg_pga_event}, 18433af36706SVinod Koul }; 18443af36706SVinod Koul 1845140adfbaSJeeja KP static const struct snd_soc_tplg_bytes_ext_ops skl_tlv_ops[] = { 1846140adfbaSJeeja KP {SKL_CONTROL_TYPE_BYTE_TLV, skl_tplg_tlv_control_get, 1847140adfbaSJeeja KP skl_tplg_tlv_control_set}, 1848140adfbaSJeeja KP }; 1849140adfbaSJeeja KP 18507a1b749bSDharageswari R static const struct snd_soc_tplg_kcontrol_ops skl_tplg_kcontrol_ops[] = { 18517a1b749bSDharageswari R { 18527a1b749bSDharageswari R .id = SKL_CONTROL_TYPE_MIC_SELECT, 18537a1b749bSDharageswari R .get = skl_tplg_mic_control_get, 18547a1b749bSDharageswari R .put = skl_tplg_mic_control_set, 18557a1b749bSDharageswari R }, 18567a1b749bSDharageswari R }; 18577a1b749bSDharageswari R 1858f6fa56e2SRamesh Babu static int skl_tplg_fill_pipe_cfg(struct device *dev, 1859f6fa56e2SRamesh Babu struct skl_pipe *pipe, u32 tkn, 1860f6fa56e2SRamesh Babu u32 tkn_val, int conf_idx, int dir) 1861f6fa56e2SRamesh Babu { 1862f6fa56e2SRamesh Babu struct skl_pipe_fmt *fmt; 1863f6fa56e2SRamesh Babu struct skl_path_config *config; 1864f6fa56e2SRamesh Babu 1865f6fa56e2SRamesh Babu switch (dir) { 1866f6fa56e2SRamesh Babu case SKL_DIR_IN: 1867f6fa56e2SRamesh Babu fmt = &pipe->configs[conf_idx].in_fmt; 1868f6fa56e2SRamesh Babu break; 1869f6fa56e2SRamesh Babu 1870f6fa56e2SRamesh Babu case SKL_DIR_OUT: 1871f6fa56e2SRamesh Babu fmt = &pipe->configs[conf_idx].out_fmt; 1872f6fa56e2SRamesh Babu break; 1873f6fa56e2SRamesh Babu 1874f6fa56e2SRamesh Babu default: 1875f6fa56e2SRamesh Babu dev_err(dev, "Invalid direction: %d\n", dir); 1876f6fa56e2SRamesh Babu return -EINVAL; 1877f6fa56e2SRamesh Babu } 1878f6fa56e2SRamesh Babu 1879f6fa56e2SRamesh Babu config = &pipe->configs[conf_idx]; 1880f6fa56e2SRamesh Babu 1881f6fa56e2SRamesh Babu switch (tkn) { 1882f6fa56e2SRamesh Babu case SKL_TKN_U32_CFG_FREQ: 1883f6fa56e2SRamesh Babu fmt->freq = tkn_val; 1884f6fa56e2SRamesh Babu break; 1885f6fa56e2SRamesh Babu 1886f6fa56e2SRamesh Babu case SKL_TKN_U8_CFG_CHAN: 1887f6fa56e2SRamesh Babu fmt->channels = tkn_val; 1888f6fa56e2SRamesh Babu break; 1889f6fa56e2SRamesh Babu 1890f6fa56e2SRamesh Babu case SKL_TKN_U8_CFG_BPS: 1891f6fa56e2SRamesh Babu fmt->bps = tkn_val; 1892f6fa56e2SRamesh Babu break; 1893f6fa56e2SRamesh Babu 1894f6fa56e2SRamesh Babu case SKL_TKN_U32_PATH_MEM_PGS: 1895f6fa56e2SRamesh Babu config->mem_pages = tkn_val; 1896f6fa56e2SRamesh Babu break; 1897f6fa56e2SRamesh Babu 1898f6fa56e2SRamesh Babu default: 1899f6fa56e2SRamesh Babu dev_err(dev, "Invalid token config: %d\n", tkn); 1900f6fa56e2SRamesh Babu return -EINVAL; 1901f6fa56e2SRamesh Babu } 1902f6fa56e2SRamesh Babu 1903f6fa56e2SRamesh Babu return 0; 1904f6fa56e2SRamesh Babu } 1905f6fa56e2SRamesh Babu 19066277e832SShreyas NC static int skl_tplg_fill_pipe_tkn(struct device *dev, 19076277e832SShreyas NC struct skl_pipe *pipe, u32 tkn, 19086277e832SShreyas NC u32 tkn_val) 19093af36706SVinod Koul { 19103af36706SVinod Koul 19116277e832SShreyas NC switch (tkn) { 19126277e832SShreyas NC case SKL_TKN_U32_PIPE_CONN_TYPE: 19136277e832SShreyas NC pipe->conn_type = tkn_val; 19146277e832SShreyas NC break; 19156277e832SShreyas NC 19166277e832SShreyas NC case SKL_TKN_U32_PIPE_PRIORITY: 19176277e832SShreyas NC pipe->pipe_priority = tkn_val; 19186277e832SShreyas NC break; 19196277e832SShreyas NC 19206277e832SShreyas NC case SKL_TKN_U32_PIPE_MEM_PGS: 19216277e832SShreyas NC pipe->memory_pages = tkn_val; 19226277e832SShreyas NC break; 19236277e832SShreyas NC 19248a0cb236SVinod Koul case SKL_TKN_U32_PMODE: 19258a0cb236SVinod Koul pipe->lp_mode = tkn_val; 19268a0cb236SVinod Koul break; 19278a0cb236SVinod Koul 1928f6fa56e2SRamesh Babu case SKL_TKN_U32_PIPE_DIRECTION: 1929f6fa56e2SRamesh Babu pipe->direction = tkn_val; 1930f6fa56e2SRamesh Babu break; 1931f6fa56e2SRamesh Babu 1932f6fa56e2SRamesh Babu case SKL_TKN_U32_NUM_CONFIGS: 1933f6fa56e2SRamesh Babu pipe->nr_cfgs = tkn_val; 1934f6fa56e2SRamesh Babu break; 1935f6fa56e2SRamesh Babu 19366277e832SShreyas NC default: 19376277e832SShreyas NC dev_err(dev, "Token not handled %d\n", tkn); 19386277e832SShreyas NC return -EINVAL; 19393af36706SVinod Koul } 19406277e832SShreyas NC 19416277e832SShreyas NC return 0; 19423af36706SVinod Koul } 19433af36706SVinod Koul 19443af36706SVinod Koul /* 19456277e832SShreyas NC * Add pipeline by parsing the relevant tokens 19466277e832SShreyas NC * Return an existing pipe if the pipe already exists. 19473af36706SVinod Koul */ 19486277e832SShreyas NC static int skl_tplg_add_pipe(struct device *dev, 1949bcc2a2dcSCezary Rojewski struct skl_module_cfg *mconfig, struct skl_dev *skl, 19506277e832SShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem) 19513af36706SVinod Koul { 19523af36706SVinod Koul struct skl_pipeline *ppl; 19533af36706SVinod Koul struct skl_pipe *pipe; 19543af36706SVinod Koul struct skl_pipe_params *params; 19553af36706SVinod Koul 19563af36706SVinod Koul list_for_each_entry(ppl, &skl->ppl_list, node) { 19576277e832SShreyas NC if (ppl->pipe->ppl_id == tkn_elem->value) { 19586277e832SShreyas NC mconfig->pipe = ppl->pipe; 1959081dc8abSGuneshwor Singh return -EEXIST; 19606277e832SShreyas NC } 19613af36706SVinod Koul } 19623af36706SVinod Koul 19633af36706SVinod Koul ppl = devm_kzalloc(dev, sizeof(*ppl), GFP_KERNEL); 19643af36706SVinod Koul if (!ppl) 19656277e832SShreyas NC return -ENOMEM; 19663af36706SVinod Koul 19673af36706SVinod Koul pipe = devm_kzalloc(dev, sizeof(*pipe), GFP_KERNEL); 19683af36706SVinod Koul if (!pipe) 19696277e832SShreyas NC return -ENOMEM; 19703af36706SVinod Koul 19713af36706SVinod Koul params = devm_kzalloc(dev, sizeof(*params), GFP_KERNEL); 19723af36706SVinod Koul if (!params) 19736277e832SShreyas NC return -ENOMEM; 19743af36706SVinod Koul 19753af36706SVinod Koul pipe->p_params = params; 19766277e832SShreyas NC pipe->ppl_id = tkn_elem->value; 19773af36706SVinod Koul INIT_LIST_HEAD(&pipe->w_list); 19783af36706SVinod Koul 19793af36706SVinod Koul ppl->pipe = pipe; 19803af36706SVinod Koul list_add(&ppl->node, &skl->ppl_list); 19813af36706SVinod Koul 19826277e832SShreyas NC mconfig->pipe = pipe; 19836277e832SShreyas NC mconfig->pipe->state = SKL_PIPE_INVALID; 19846277e832SShreyas NC 19856277e832SShreyas NC return 0; 19863af36706SVinod Koul } 19873af36706SVinod Koul 19889e0784d0SAndy Shevchenko static int skl_tplg_get_uuid(struct device *dev, guid_t *guid, 198922ebd666SSriram Periyasamy struct snd_soc_tplg_vendor_uuid_elem *uuid_tkn) 19906277e832SShreyas NC { 199122ebd666SSriram Periyasamy if (uuid_tkn->token == SKL_TKN_UUID) { 1992cade2f59SAndy Shevchenko import_guid(guid, uuid_tkn->uuid); 199322ebd666SSriram Periyasamy return 0; 199422ebd666SSriram Periyasamy } 199522ebd666SSriram Periyasamy 199622ebd666SSriram Periyasamy dev_err(dev, "Not an UUID token %d\n", uuid_tkn->token); 199722ebd666SSriram Periyasamy 199822ebd666SSriram Periyasamy return -EINVAL; 199922ebd666SSriram Periyasamy } 200022ebd666SSriram Periyasamy 200122ebd666SSriram Periyasamy static int skl_tplg_fill_pin(struct device *dev, 200222ebd666SSriram Periyasamy struct snd_soc_tplg_vendor_value_elem *tkn_elem, 200322ebd666SSriram Periyasamy struct skl_module_pin *m_pin, 200422ebd666SSriram Periyasamy int pin_index) 200522ebd666SSriram Periyasamy { 2006d9561474SSriram Periyasamy int ret; 2007d9561474SSriram Periyasamy 200822ebd666SSriram Periyasamy switch (tkn_elem->token) { 20096277e832SShreyas NC case SKL_TKN_U32_PIN_MOD_ID: 201022ebd666SSriram Periyasamy m_pin[pin_index].id.module_id = tkn_elem->value; 20116277e832SShreyas NC break; 20126277e832SShreyas NC 20136277e832SShreyas NC case SKL_TKN_U32_PIN_INST_ID: 201422ebd666SSriram Periyasamy m_pin[pin_index].id.instance_id = tkn_elem->value; 20156277e832SShreyas NC break; 20166277e832SShreyas NC 2017d9561474SSriram Periyasamy case SKL_TKN_UUID: 20189e0784d0SAndy Shevchenko ret = skl_tplg_get_uuid(dev, &m_pin[pin_index].id.mod_uuid, 2019d9561474SSriram Periyasamy (struct snd_soc_tplg_vendor_uuid_elem *)tkn_elem); 2020d9561474SSriram Periyasamy if (ret < 0) 2021d9561474SSriram Periyasamy return ret; 2022d9561474SSriram Periyasamy 20236277e832SShreyas NC break; 20246277e832SShreyas NC 20256277e832SShreyas NC default: 202622ebd666SSriram Periyasamy dev_err(dev, "%d Not a pin token\n", tkn_elem->token); 20276277e832SShreyas NC return -EINVAL; 20286277e832SShreyas NC } 20296277e832SShreyas NC 20306277e832SShreyas NC return 0; 20316277e832SShreyas NC } 20326277e832SShreyas NC 20336277e832SShreyas NC /* 20346277e832SShreyas NC * Parse for pin config specific tokens to fill up the 20356277e832SShreyas NC * module private data 20366277e832SShreyas NC */ 20376277e832SShreyas NC static int skl_tplg_fill_pins_info(struct device *dev, 20386277e832SShreyas NC struct skl_module_cfg *mconfig, 20396277e832SShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem, 20406277e832SShreyas NC int dir, int pin_count) 20416277e832SShreyas NC { 20426277e832SShreyas NC int ret; 20436277e832SShreyas NC struct skl_module_pin *m_pin; 20446277e832SShreyas NC 20456277e832SShreyas NC switch (dir) { 20466277e832SShreyas NC case SKL_DIR_IN: 20476277e832SShreyas NC m_pin = mconfig->m_in_pin; 20486277e832SShreyas NC break; 20496277e832SShreyas NC 20506277e832SShreyas NC case SKL_DIR_OUT: 20516277e832SShreyas NC m_pin = mconfig->m_out_pin; 20526277e832SShreyas NC break; 20536277e832SShreyas NC 20546277e832SShreyas NC default: 2055ecd286a9SColin Ian King dev_err(dev, "Invalid direction value\n"); 20566277e832SShreyas NC return -EINVAL; 20576277e832SShreyas NC } 20586277e832SShreyas NC 205922ebd666SSriram Periyasamy ret = skl_tplg_fill_pin(dev, tkn_elem, m_pin, pin_count); 20606277e832SShreyas NC if (ret < 0) 20616277e832SShreyas NC return ret; 20626277e832SShreyas NC 20636277e832SShreyas NC m_pin[pin_count].in_use = false; 20646277e832SShreyas NC m_pin[pin_count].pin_state = SKL_PIN_UNBIND; 20656277e832SShreyas NC 20666277e832SShreyas NC return 0; 20676277e832SShreyas NC } 20686277e832SShreyas NC 20696277e832SShreyas NC /* 20706277e832SShreyas NC * Fill up input/output module config format based 20716277e832SShreyas NC * on the direction 20726277e832SShreyas NC */ 20736277e832SShreyas NC static int skl_tplg_fill_fmt(struct device *dev, 2074ca312fdaSShreyas NC struct skl_module_fmt *dst_fmt, 2075ca312fdaSShreyas NC u32 tkn, u32 value) 20766277e832SShreyas NC { 20776277e832SShreyas NC switch (tkn) { 20786277e832SShreyas NC case SKL_TKN_U32_FMT_CH: 20796277e832SShreyas NC dst_fmt->channels = value; 20806277e832SShreyas NC break; 20816277e832SShreyas NC 20826277e832SShreyas NC case SKL_TKN_U32_FMT_FREQ: 20836277e832SShreyas NC dst_fmt->s_freq = value; 20846277e832SShreyas NC break; 20856277e832SShreyas NC 20866277e832SShreyas NC case SKL_TKN_U32_FMT_BIT_DEPTH: 20876277e832SShreyas NC dst_fmt->bit_depth = value; 20886277e832SShreyas NC break; 20896277e832SShreyas NC 20906277e832SShreyas NC case SKL_TKN_U32_FMT_SAMPLE_SIZE: 20916277e832SShreyas NC dst_fmt->valid_bit_depth = value; 20926277e832SShreyas NC break; 20936277e832SShreyas NC 20946277e832SShreyas NC case SKL_TKN_U32_FMT_CH_CONFIG: 20956277e832SShreyas NC dst_fmt->ch_cfg = value; 20966277e832SShreyas NC break; 20976277e832SShreyas NC 20986277e832SShreyas NC case SKL_TKN_U32_FMT_INTERLEAVE: 20996277e832SShreyas NC dst_fmt->interleaving_style = value; 21006277e832SShreyas NC break; 21016277e832SShreyas NC 21026277e832SShreyas NC case SKL_TKN_U32_FMT_SAMPLE_TYPE: 21036277e832SShreyas NC dst_fmt->sample_type = value; 21046277e832SShreyas NC break; 21056277e832SShreyas NC 21066277e832SShreyas NC case SKL_TKN_U32_FMT_CH_MAP: 21076277e832SShreyas NC dst_fmt->ch_map = value; 21086277e832SShreyas NC break; 21096277e832SShreyas NC 21106277e832SShreyas NC default: 2111ecd286a9SColin Ian King dev_err(dev, "Invalid token %d\n", tkn); 21126277e832SShreyas NC return -EINVAL; 21136277e832SShreyas NC } 21146277e832SShreyas NC 21156277e832SShreyas NC return 0; 21166277e832SShreyas NC } 21176277e832SShreyas NC 2118ca312fdaSShreyas NC static int skl_tplg_widget_fill_fmt(struct device *dev, 2119f6fa56e2SRamesh Babu struct skl_module_iface *fmt, 2120ca312fdaSShreyas NC u32 tkn, u32 val, u32 dir, int fmt_idx) 2121ca312fdaSShreyas NC { 2122ca312fdaSShreyas NC struct skl_module_fmt *dst_fmt; 2123ca312fdaSShreyas NC 2124f6fa56e2SRamesh Babu if (!fmt) 2125f6fa56e2SRamesh Babu return -EINVAL; 2126f6fa56e2SRamesh Babu 2127ca312fdaSShreyas NC switch (dir) { 2128ca312fdaSShreyas NC case SKL_DIR_IN: 2129f6fa56e2SRamesh Babu dst_fmt = &fmt->inputs[fmt_idx].fmt; 2130ca312fdaSShreyas NC break; 2131ca312fdaSShreyas NC 2132ca312fdaSShreyas NC case SKL_DIR_OUT: 2133f6fa56e2SRamesh Babu dst_fmt = &fmt->outputs[fmt_idx].fmt; 2134ca312fdaSShreyas NC break; 2135ca312fdaSShreyas NC 2136ca312fdaSShreyas NC default: 2137ca312fdaSShreyas NC dev_err(dev, "Invalid direction: %d\n", dir); 2138ca312fdaSShreyas NC return -EINVAL; 2139ca312fdaSShreyas NC } 2140ca312fdaSShreyas NC 2141ca312fdaSShreyas NC return skl_tplg_fill_fmt(dev, dst_fmt, tkn, val); 2142ca312fdaSShreyas NC } 2143ca312fdaSShreyas NC 21446277e832SShreyas NC static void skl_tplg_fill_pin_dynamic_val( 21456277e832SShreyas NC struct skl_module_pin *mpin, u32 pin_count, u32 value) 21464cd9899fSHardik T Shah { 21474cd9899fSHardik T Shah int i; 21484cd9899fSHardik T Shah 21496277e832SShreyas NC for (i = 0; i < pin_count; i++) 21506277e832SShreyas NC mpin[i].is_dynamic = value; 21514cd9899fSHardik T Shah } 21526277e832SShreyas NC 21536277e832SShreyas NC /* 2154db6ed55dSShreyas NC * Resource table in the manifest has pin specific resources 2155db6ed55dSShreyas NC * like pin and pin buffer size 2156db6ed55dSShreyas NC */ 2157db6ed55dSShreyas NC static int skl_tplg_manifest_pin_res_tkn(struct device *dev, 2158db6ed55dSShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem, 2159db6ed55dSShreyas NC struct skl_module_res *res, int pin_idx, int dir) 2160db6ed55dSShreyas NC { 2161db6ed55dSShreyas NC struct skl_module_pin_resources *m_pin; 2162db6ed55dSShreyas NC 2163db6ed55dSShreyas NC switch (dir) { 2164db6ed55dSShreyas NC case SKL_DIR_IN: 2165db6ed55dSShreyas NC m_pin = &res->input[pin_idx]; 2166db6ed55dSShreyas NC break; 2167db6ed55dSShreyas NC 2168db6ed55dSShreyas NC case SKL_DIR_OUT: 2169db6ed55dSShreyas NC m_pin = &res->output[pin_idx]; 2170db6ed55dSShreyas NC break; 2171db6ed55dSShreyas NC 2172db6ed55dSShreyas NC default: 2173db6ed55dSShreyas NC dev_err(dev, "Invalid pin direction: %d\n", dir); 2174db6ed55dSShreyas NC return -EINVAL; 2175db6ed55dSShreyas NC } 2176db6ed55dSShreyas NC 2177db6ed55dSShreyas NC switch (tkn_elem->token) { 2178db6ed55dSShreyas NC case SKL_TKN_MM_U32_RES_PIN_ID: 2179db6ed55dSShreyas NC m_pin->pin_index = tkn_elem->value; 2180db6ed55dSShreyas NC break; 2181db6ed55dSShreyas NC 2182db6ed55dSShreyas NC case SKL_TKN_MM_U32_PIN_BUF: 2183db6ed55dSShreyas NC m_pin->buf_size = tkn_elem->value; 2184db6ed55dSShreyas NC break; 2185db6ed55dSShreyas NC 2186db6ed55dSShreyas NC default: 2187db6ed55dSShreyas NC dev_err(dev, "Invalid token: %d\n", tkn_elem->token); 2188db6ed55dSShreyas NC return -EINVAL; 2189db6ed55dSShreyas NC } 2190db6ed55dSShreyas NC 2191db6ed55dSShreyas NC return 0; 2192db6ed55dSShreyas NC } 2193db6ed55dSShreyas NC 2194db6ed55dSShreyas NC /* 2195db6ed55dSShreyas NC * Fill module specific resources from the manifest's resource 2196db6ed55dSShreyas NC * table like CPS, DMA size, mem_pages. 2197db6ed55dSShreyas NC */ 2198db6ed55dSShreyas NC static int skl_tplg_fill_res_tkn(struct device *dev, 2199db6ed55dSShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem, 2200db6ed55dSShreyas NC struct skl_module_res *res, 2201db6ed55dSShreyas NC int pin_idx, int dir) 2202db6ed55dSShreyas NC { 2203db6ed55dSShreyas NC int ret, tkn_count = 0; 2204db6ed55dSShreyas NC 2205db6ed55dSShreyas NC if (!res) 2206db6ed55dSShreyas NC return -EINVAL; 2207db6ed55dSShreyas NC 2208db6ed55dSShreyas NC switch (tkn_elem->token) { 2209db6ed55dSShreyas NC case SKL_TKN_MM_U32_DMA_SIZE: 2210db6ed55dSShreyas NC res->dma_buffer_size = tkn_elem->value; 2211db6ed55dSShreyas NC break; 2212db6ed55dSShreyas NC 2213db6ed55dSShreyas NC case SKL_TKN_MM_U32_CPC: 2214db6ed55dSShreyas NC res->cpc = tkn_elem->value; 2215db6ed55dSShreyas NC break; 2216db6ed55dSShreyas NC 2217db6ed55dSShreyas NC case SKL_TKN_U32_MEM_PAGES: 2218db6ed55dSShreyas NC res->is_pages = tkn_elem->value; 2219db6ed55dSShreyas NC break; 2220db6ed55dSShreyas NC 2221db6ed55dSShreyas NC case SKL_TKN_U32_OBS: 2222db6ed55dSShreyas NC res->obs = tkn_elem->value; 2223db6ed55dSShreyas NC break; 2224db6ed55dSShreyas NC 2225db6ed55dSShreyas NC case SKL_TKN_U32_IBS: 2226db6ed55dSShreyas NC res->ibs = tkn_elem->value; 2227db6ed55dSShreyas NC break; 2228db6ed55dSShreyas NC 2229db6ed55dSShreyas NC case SKL_TKN_MM_U32_RES_PIN_ID: 2230db6ed55dSShreyas NC case SKL_TKN_MM_U32_PIN_BUF: 2231db6ed55dSShreyas NC ret = skl_tplg_manifest_pin_res_tkn(dev, tkn_elem, res, 2232db6ed55dSShreyas NC pin_idx, dir); 2233db6ed55dSShreyas NC if (ret < 0) 2234db6ed55dSShreyas NC return ret; 2235db6ed55dSShreyas NC break; 2236db6ed55dSShreyas NC 223784b71067SCezary Rojewski case SKL_TKN_MM_U32_CPS: 223884b71067SCezary Rojewski case SKL_TKN_U32_MAX_MCPS: 223984b71067SCezary Rojewski /* ignore unused tokens */ 224084b71067SCezary Rojewski break; 224184b71067SCezary Rojewski 2242db6ed55dSShreyas NC default: 2243db6ed55dSShreyas NC dev_err(dev, "Not a res type token: %d", tkn_elem->token); 2244db6ed55dSShreyas NC return -EINVAL; 2245db6ed55dSShreyas NC 2246db6ed55dSShreyas NC } 2247db6ed55dSShreyas NC tkn_count++; 2248db6ed55dSShreyas NC 2249db6ed55dSShreyas NC return tkn_count; 2250db6ed55dSShreyas NC } 2251db6ed55dSShreyas NC 2252db6ed55dSShreyas NC /* 22536277e832SShreyas NC * Parse tokens to fill up the module private data 22546277e832SShreyas NC */ 22556277e832SShreyas NC static int skl_tplg_get_token(struct device *dev, 22566277e832SShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem, 2257bcc2a2dcSCezary Rojewski struct skl_dev *skl, struct skl_module_cfg *mconfig) 22586277e832SShreyas NC { 22596277e832SShreyas NC int tkn_count = 0; 22606277e832SShreyas NC int ret; 22616277e832SShreyas NC static int is_pipe_exists; 2262f6fa56e2SRamesh Babu static int pin_index, dir, conf_idx; 2263f6fa56e2SRamesh Babu struct skl_module_iface *iface = NULL; 2264f6fa56e2SRamesh Babu struct skl_module_res *res = NULL; 2265f6fa56e2SRamesh Babu int res_idx = mconfig->res_idx; 2266f6fa56e2SRamesh Babu int fmt_idx = mconfig->fmt_idx; 2267f6fa56e2SRamesh Babu 2268f6fa56e2SRamesh Babu /* 2269f6fa56e2SRamesh Babu * If the manifest structure contains no modules, fill all 2270f6fa56e2SRamesh Babu * the module data to 0th index. 2271f6fa56e2SRamesh Babu * res_idx and fmt_idx are default set to 0. 2272f6fa56e2SRamesh Babu */ 2273f6fa56e2SRamesh Babu if (skl->nr_modules == 0) { 2274f6fa56e2SRamesh Babu res = &mconfig->module->resources[res_idx]; 2275f6fa56e2SRamesh Babu iface = &mconfig->module->formats[fmt_idx]; 2276f6fa56e2SRamesh Babu } 22776277e832SShreyas NC 22786277e832SShreyas NC if (tkn_elem->token > SKL_TKN_MAX) 22796277e832SShreyas NC return -EINVAL; 22806277e832SShreyas NC 22816277e832SShreyas NC switch (tkn_elem->token) { 22826277e832SShreyas NC case SKL_TKN_U8_IN_QUEUE_COUNT: 2283f6fa56e2SRamesh Babu mconfig->module->max_input_pins = tkn_elem->value; 22846277e832SShreyas NC break; 22856277e832SShreyas NC 22866277e832SShreyas NC case SKL_TKN_U8_OUT_QUEUE_COUNT: 2287f6fa56e2SRamesh Babu mconfig->module->max_output_pins = tkn_elem->value; 22886277e832SShreyas NC break; 22896277e832SShreyas NC 22906277e832SShreyas NC case SKL_TKN_U8_DYN_IN_PIN: 22916277e832SShreyas NC if (!mconfig->m_in_pin) 2292a86854d0SKees Cook mconfig->m_in_pin = 2293a86854d0SKees Cook devm_kcalloc(dev, MAX_IN_QUEUE, 2294a86854d0SKees Cook sizeof(*mconfig->m_in_pin), 2295a86854d0SKees Cook GFP_KERNEL); 2296f6fa56e2SRamesh Babu if (!mconfig->m_in_pin) 22976277e832SShreyas NC return -ENOMEM; 22986277e832SShreyas NC 2299f6fa56e2SRamesh Babu skl_tplg_fill_pin_dynamic_val(mconfig->m_in_pin, MAX_IN_QUEUE, 2300f6fa56e2SRamesh Babu tkn_elem->value); 23016277e832SShreyas NC break; 23026277e832SShreyas NC 23036277e832SShreyas NC case SKL_TKN_U8_DYN_OUT_PIN: 23046277e832SShreyas NC if (!mconfig->m_out_pin) 2305a86854d0SKees Cook mconfig->m_out_pin = 2306a86854d0SKees Cook devm_kcalloc(dev, MAX_IN_QUEUE, 2307a86854d0SKees Cook sizeof(*mconfig->m_in_pin), 2308a86854d0SKees Cook GFP_KERNEL); 2309f6fa56e2SRamesh Babu if (!mconfig->m_out_pin) 23106277e832SShreyas NC return -ENOMEM; 23116277e832SShreyas NC 2312f6fa56e2SRamesh Babu skl_tplg_fill_pin_dynamic_val(mconfig->m_out_pin, MAX_OUT_QUEUE, 2313f6fa56e2SRamesh Babu tkn_elem->value); 23146277e832SShreyas NC break; 23156277e832SShreyas NC 23166277e832SShreyas NC case SKL_TKN_U8_TIME_SLOT: 23176277e832SShreyas NC mconfig->time_slot = tkn_elem->value; 23186277e832SShreyas NC break; 23196277e832SShreyas NC 23206277e832SShreyas NC case SKL_TKN_U8_CORE_ID: 23216277e832SShreyas NC mconfig->core_id = tkn_elem->value; 23229c80c5a8STakashi Iwai break; 23236277e832SShreyas NC 23246277e832SShreyas NC case SKL_TKN_U8_MOD_TYPE: 23256277e832SShreyas NC mconfig->m_type = tkn_elem->value; 23266277e832SShreyas NC break; 23276277e832SShreyas NC 23286277e832SShreyas NC case SKL_TKN_U8_DEV_TYPE: 23296277e832SShreyas NC mconfig->dev_type = tkn_elem->value; 23306277e832SShreyas NC break; 23316277e832SShreyas NC 23326277e832SShreyas NC case SKL_TKN_U8_HW_CONN_TYPE: 23336277e832SShreyas NC mconfig->hw_conn_type = tkn_elem->value; 23346277e832SShreyas NC break; 23356277e832SShreyas NC 23366277e832SShreyas NC case SKL_TKN_U16_MOD_INST_ID: 23376277e832SShreyas NC mconfig->id.instance_id = 23386277e832SShreyas NC tkn_elem->value; 23396277e832SShreyas NC break; 23406277e832SShreyas NC 23416277e832SShreyas NC case SKL_TKN_U32_MEM_PAGES: 23426277e832SShreyas NC case SKL_TKN_U32_MAX_MCPS: 23436277e832SShreyas NC case SKL_TKN_U32_OBS: 23446277e832SShreyas NC case SKL_TKN_U32_IBS: 23452b79b15cSColin Ian King ret = skl_tplg_fill_res_tkn(dev, tkn_elem, res, pin_index, dir); 2346f6fa56e2SRamesh Babu if (ret < 0) 2347f6fa56e2SRamesh Babu return ret; 2348f6fa56e2SRamesh Babu 23496277e832SShreyas NC break; 23506277e832SShreyas NC 23516277e832SShreyas NC case SKL_TKN_U32_VBUS_ID: 23526277e832SShreyas NC mconfig->vbus_id = tkn_elem->value; 23536277e832SShreyas NC break; 23546277e832SShreyas NC 23556277e832SShreyas NC case SKL_TKN_U32_PARAMS_FIXUP: 23566277e832SShreyas NC mconfig->params_fixup = tkn_elem->value; 23576277e832SShreyas NC break; 23586277e832SShreyas NC 23596277e832SShreyas NC case SKL_TKN_U32_CONVERTER: 23606277e832SShreyas NC mconfig->converter = tkn_elem->value; 23616277e832SShreyas NC break; 23626277e832SShreyas NC 2363c0116be3SSubhransu S. Prusty case SKL_TKN_U32_D0I3_CAPS: 23646bd9dcf3SVinod Koul mconfig->d0i3_caps = tkn_elem->value; 23656bd9dcf3SVinod Koul break; 23666bd9dcf3SVinod Koul 23676277e832SShreyas NC case SKL_TKN_U32_PIPE_ID: 23686277e832SShreyas NC ret = skl_tplg_add_pipe(dev, 23696277e832SShreyas NC mconfig, skl, tkn_elem); 23706277e832SShreyas NC 2371081dc8abSGuneshwor Singh if (ret < 0) { 2372081dc8abSGuneshwor Singh if (ret == -EEXIST) { 23736277e832SShreyas NC is_pipe_exists = 1; 2374081dc8abSGuneshwor Singh break; 2375081dc8abSGuneshwor Singh } 2376081dc8abSGuneshwor Singh return is_pipe_exists; 2377081dc8abSGuneshwor Singh } 23786277e832SShreyas NC 23796277e832SShreyas NC break; 23806277e832SShreyas NC 2381f6fa56e2SRamesh Babu case SKL_TKN_U32_PIPE_CONFIG_ID: 2382f6fa56e2SRamesh Babu conf_idx = tkn_elem->value; 2383f6fa56e2SRamesh Babu break; 2384f6fa56e2SRamesh Babu 23856277e832SShreyas NC case SKL_TKN_U32_PIPE_CONN_TYPE: 23866277e832SShreyas NC case SKL_TKN_U32_PIPE_PRIORITY: 23876277e832SShreyas NC case SKL_TKN_U32_PIPE_MEM_PGS: 23888a0cb236SVinod Koul case SKL_TKN_U32_PMODE: 2389f6fa56e2SRamesh Babu case SKL_TKN_U32_PIPE_DIRECTION: 2390f6fa56e2SRamesh Babu case SKL_TKN_U32_NUM_CONFIGS: 23916277e832SShreyas NC if (is_pipe_exists) { 23926277e832SShreyas NC ret = skl_tplg_fill_pipe_tkn(dev, mconfig->pipe, 23936277e832SShreyas NC tkn_elem->token, tkn_elem->value); 23946277e832SShreyas NC if (ret < 0) 23956277e832SShreyas NC return ret; 23966277e832SShreyas NC } 23976277e832SShreyas NC 23986277e832SShreyas NC break; 23996277e832SShreyas NC 2400f6fa56e2SRamesh Babu case SKL_TKN_U32_PATH_MEM_PGS: 2401f6fa56e2SRamesh Babu case SKL_TKN_U32_CFG_FREQ: 2402f6fa56e2SRamesh Babu case SKL_TKN_U8_CFG_CHAN: 2403f6fa56e2SRamesh Babu case SKL_TKN_U8_CFG_BPS: 2404f6fa56e2SRamesh Babu if (mconfig->pipe->nr_cfgs) { 2405f6fa56e2SRamesh Babu ret = skl_tplg_fill_pipe_cfg(dev, mconfig->pipe, 2406f6fa56e2SRamesh Babu tkn_elem->token, tkn_elem->value, 2407f6fa56e2SRamesh Babu conf_idx, dir); 2408f6fa56e2SRamesh Babu if (ret < 0) 2409f6fa56e2SRamesh Babu return ret; 2410f6fa56e2SRamesh Babu } 2411f6fa56e2SRamesh Babu break; 2412f6fa56e2SRamesh Babu 2413f6fa56e2SRamesh Babu case SKL_TKN_CFG_MOD_RES_ID: 2414f6fa56e2SRamesh Babu mconfig->mod_cfg[conf_idx].res_idx = tkn_elem->value; 2415f6fa56e2SRamesh Babu break; 2416f6fa56e2SRamesh Babu 2417f6fa56e2SRamesh Babu case SKL_TKN_CFG_MOD_FMT_ID: 2418f6fa56e2SRamesh Babu mconfig->mod_cfg[conf_idx].fmt_idx = tkn_elem->value; 2419f6fa56e2SRamesh Babu break; 2420f6fa56e2SRamesh Babu 24216277e832SShreyas NC /* 24226277e832SShreyas NC * SKL_TKN_U32_DIR_PIN_COUNT token has the value for both 24236277e832SShreyas NC * direction and the pin count. The first four bits represent 24246277e832SShreyas NC * direction and next four the pin count. 24256277e832SShreyas NC */ 24266277e832SShreyas NC case SKL_TKN_U32_DIR_PIN_COUNT: 24276277e832SShreyas NC dir = tkn_elem->value & SKL_IN_DIR_BIT_MASK; 24286277e832SShreyas NC pin_index = (tkn_elem->value & 24296277e832SShreyas NC SKL_PIN_COUNT_MASK) >> 4; 24306277e832SShreyas NC 24316277e832SShreyas NC break; 24326277e832SShreyas NC 24336277e832SShreyas NC case SKL_TKN_U32_FMT_CH: 24346277e832SShreyas NC case SKL_TKN_U32_FMT_FREQ: 24356277e832SShreyas NC case SKL_TKN_U32_FMT_BIT_DEPTH: 24366277e832SShreyas NC case SKL_TKN_U32_FMT_SAMPLE_SIZE: 24376277e832SShreyas NC case SKL_TKN_U32_FMT_CH_CONFIG: 24386277e832SShreyas NC case SKL_TKN_U32_FMT_INTERLEAVE: 24396277e832SShreyas NC case SKL_TKN_U32_FMT_SAMPLE_TYPE: 24406277e832SShreyas NC case SKL_TKN_U32_FMT_CH_MAP: 2441f6fa56e2SRamesh Babu ret = skl_tplg_widget_fill_fmt(dev, iface, tkn_elem->token, 24426277e832SShreyas NC tkn_elem->value, dir, pin_index); 24436277e832SShreyas NC 24446277e832SShreyas NC if (ret < 0) 24456277e832SShreyas NC return ret; 24466277e832SShreyas NC 24476277e832SShreyas NC break; 24486277e832SShreyas NC 24496277e832SShreyas NC case SKL_TKN_U32_PIN_MOD_ID: 24506277e832SShreyas NC case SKL_TKN_U32_PIN_INST_ID: 2451d9561474SSriram Periyasamy case SKL_TKN_UUID: 24526277e832SShreyas NC ret = skl_tplg_fill_pins_info(dev, 24536277e832SShreyas NC mconfig, tkn_elem, dir, 24546277e832SShreyas NC pin_index); 24556277e832SShreyas NC if (ret < 0) 24566277e832SShreyas NC return ret; 24576277e832SShreyas NC 24586277e832SShreyas NC break; 24596277e832SShreyas NC 24606277e832SShreyas NC case SKL_TKN_U32_CAPS_SIZE: 24616277e832SShreyas NC mconfig->formats_config.caps_size = 24626277e832SShreyas NC tkn_elem->value; 24636277e832SShreyas NC 24646277e832SShreyas NC break; 24656277e832SShreyas NC 2466133e6e5cSShreyas NC case SKL_TKN_U32_CAPS_SET_PARAMS: 2467133e6e5cSShreyas NC mconfig->formats_config.set_params = 2468133e6e5cSShreyas NC tkn_elem->value; 2469133e6e5cSShreyas NC break; 2470133e6e5cSShreyas NC 2471133e6e5cSShreyas NC case SKL_TKN_U32_CAPS_PARAMS_ID: 2472133e6e5cSShreyas NC mconfig->formats_config.param_id = 2473133e6e5cSShreyas NC tkn_elem->value; 2474133e6e5cSShreyas NC break; 2475133e6e5cSShreyas NC 24766277e832SShreyas NC case SKL_TKN_U32_PROC_DOMAIN: 24776277e832SShreyas NC mconfig->domain = 24786277e832SShreyas NC tkn_elem->value; 24796277e832SShreyas NC 24806277e832SShreyas NC break; 24816277e832SShreyas NC 2482939df3adSRamesh Babu case SKL_TKN_U32_DMA_BUF_SIZE: 2483939df3adSRamesh Babu mconfig->dma_buffer_size = tkn_elem->value; 2484939df3adSRamesh Babu break; 2485939df3adSRamesh Babu 24866277e832SShreyas NC case SKL_TKN_U8_IN_PIN_TYPE: 24876277e832SShreyas NC case SKL_TKN_U8_OUT_PIN_TYPE: 24886277e832SShreyas NC case SKL_TKN_U8_CONN_TYPE: 24896277e832SShreyas NC break; 24906277e832SShreyas NC 24916277e832SShreyas NC default: 24926277e832SShreyas NC dev_err(dev, "Token %d not handled\n", 24936277e832SShreyas NC tkn_elem->token); 24946277e832SShreyas NC return -EINVAL; 24956277e832SShreyas NC } 24966277e832SShreyas NC 24976277e832SShreyas NC tkn_count++; 24986277e832SShreyas NC 24996277e832SShreyas NC return tkn_count; 25006277e832SShreyas NC } 25016277e832SShreyas NC 25026277e832SShreyas NC /* 25036277e832SShreyas NC * Parse the vendor array for specific tokens to construct 25046277e832SShreyas NC * module private data 25056277e832SShreyas NC */ 25066277e832SShreyas NC static int skl_tplg_get_tokens(struct device *dev, 2507bcc2a2dcSCezary Rojewski char *pvt_data, struct skl_dev *skl, 25086277e832SShreyas NC struct skl_module_cfg *mconfig, int block_size) 25096277e832SShreyas NC { 25106277e832SShreyas NC struct snd_soc_tplg_vendor_array *array; 25116277e832SShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem; 25126277e832SShreyas NC int tkn_count = 0, ret; 25136277e832SShreyas NC int off = 0, tuple_size = 0; 2514d9561474SSriram Periyasamy bool is_module_guid = true; 25156277e832SShreyas NC 25166277e832SShreyas NC if (block_size <= 0) 25176277e832SShreyas NC return -EINVAL; 25186277e832SShreyas NC 25196277e832SShreyas NC while (tuple_size < block_size) { 25206277e832SShreyas NC array = (struct snd_soc_tplg_vendor_array *)(pvt_data + off); 25216277e832SShreyas NC 25226277e832SShreyas NC off += array->size; 25236277e832SShreyas NC 25246277e832SShreyas NC switch (array->type) { 25256277e832SShreyas NC case SND_SOC_TPLG_TUPLE_TYPE_STRING: 2526ecd286a9SColin Ian King dev_warn(dev, "no string tokens expected for skl tplg\n"); 25276277e832SShreyas NC continue; 25286277e832SShreyas NC 25296277e832SShreyas NC case SND_SOC_TPLG_TUPLE_TYPE_UUID: 2530d9561474SSriram Periyasamy if (is_module_guid) { 25319e0784d0SAndy Shevchenko ret = skl_tplg_get_uuid(dev, (guid_t *)mconfig->guid, 253222ebd666SSriram Periyasamy array->uuid); 2533d9561474SSriram Periyasamy is_module_guid = false; 2534d9561474SSriram Periyasamy } else { 2535d9561474SSriram Periyasamy ret = skl_tplg_get_token(dev, array->value, skl, 2536d9561474SSriram Periyasamy mconfig); 2537d9561474SSriram Periyasamy } 2538d9561474SSriram Periyasamy 25396277e832SShreyas NC if (ret < 0) 25406277e832SShreyas NC return ret; 25416277e832SShreyas NC 25426277e832SShreyas NC tuple_size += sizeof(*array->uuid); 25436277e832SShreyas NC 25446277e832SShreyas NC continue; 25456277e832SShreyas NC 25466277e832SShreyas NC default: 25476277e832SShreyas NC tkn_elem = array->value; 25486277e832SShreyas NC tkn_count = 0; 25496277e832SShreyas NC break; 25506277e832SShreyas NC } 25516277e832SShreyas NC 25526277e832SShreyas NC while (tkn_count <= (array->num_elems - 1)) { 25536277e832SShreyas NC ret = skl_tplg_get_token(dev, tkn_elem, 25546277e832SShreyas NC skl, mconfig); 25556277e832SShreyas NC 25566277e832SShreyas NC if (ret < 0) 25576277e832SShreyas NC return ret; 25586277e832SShreyas NC 25596277e832SShreyas NC tkn_count = tkn_count + ret; 25606277e832SShreyas NC tkn_elem++; 25616277e832SShreyas NC } 25626277e832SShreyas NC 25636277e832SShreyas NC tuple_size += tkn_count * sizeof(*tkn_elem); 25646277e832SShreyas NC } 25656277e832SShreyas NC 2566133e6e5cSShreyas NC return off; 25676277e832SShreyas NC } 25686277e832SShreyas NC 25696277e832SShreyas NC /* 25706277e832SShreyas NC * Every data block is preceded by a descriptor to read the number 25716277e832SShreyas NC * of data blocks, they type of the block and it's size 25726277e832SShreyas NC */ 25736277e832SShreyas NC static int skl_tplg_get_desc_blocks(struct device *dev, 25746277e832SShreyas NC struct snd_soc_tplg_vendor_array *array) 25756277e832SShreyas NC { 25766277e832SShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem; 25776277e832SShreyas NC 25786277e832SShreyas NC tkn_elem = array->value; 25796277e832SShreyas NC 25806277e832SShreyas NC switch (tkn_elem->token) { 25816277e832SShreyas NC case SKL_TKN_U8_NUM_BLOCKS: 25826277e832SShreyas NC case SKL_TKN_U8_BLOCK_TYPE: 25836277e832SShreyas NC case SKL_TKN_U16_BLOCK_SIZE: 25846277e832SShreyas NC return tkn_elem->value; 25856277e832SShreyas NC 25866277e832SShreyas NC default: 2587ecd286a9SColin Ian King dev_err(dev, "Invalid descriptor token %d\n", tkn_elem->token); 25886277e832SShreyas NC break; 25896277e832SShreyas NC } 25906277e832SShreyas NC 25916277e832SShreyas NC return -EINVAL; 25926277e832SShreyas NC } 25936277e832SShreyas NC 2594ac9391daSGuenter Roeck /* Functions to parse private data from configuration file format v4 */ 2595ac9391daSGuenter Roeck 2596ac9391daSGuenter Roeck /* 2597ac9391daSGuenter Roeck * Add pipeline from topology binary into driver pipeline list 2598ac9391daSGuenter Roeck * 2599ac9391daSGuenter Roeck * If already added we return that instance 2600ac9391daSGuenter Roeck * Otherwise we create a new instance and add into driver list 2601ac9391daSGuenter Roeck */ 2602ac9391daSGuenter Roeck static int skl_tplg_add_pipe_v4(struct device *dev, 2603bcc2a2dcSCezary Rojewski struct skl_module_cfg *mconfig, struct skl_dev *skl, 2604ac9391daSGuenter Roeck struct skl_dfw_v4_pipe *dfw_pipe) 2605ac9391daSGuenter Roeck { 2606ac9391daSGuenter Roeck struct skl_pipeline *ppl; 2607ac9391daSGuenter Roeck struct skl_pipe *pipe; 2608ac9391daSGuenter Roeck struct skl_pipe_params *params; 2609ac9391daSGuenter Roeck 2610ac9391daSGuenter Roeck list_for_each_entry(ppl, &skl->ppl_list, node) { 2611ac9391daSGuenter Roeck if (ppl->pipe->ppl_id == dfw_pipe->pipe_id) { 2612ac9391daSGuenter Roeck mconfig->pipe = ppl->pipe; 2613ac9391daSGuenter Roeck return 0; 2614ac9391daSGuenter Roeck } 2615ac9391daSGuenter Roeck } 2616ac9391daSGuenter Roeck 2617ac9391daSGuenter Roeck ppl = devm_kzalloc(dev, sizeof(*ppl), GFP_KERNEL); 2618ac9391daSGuenter Roeck if (!ppl) 2619ac9391daSGuenter Roeck return -ENOMEM; 2620ac9391daSGuenter Roeck 2621ac9391daSGuenter Roeck pipe = devm_kzalloc(dev, sizeof(*pipe), GFP_KERNEL); 2622ac9391daSGuenter Roeck if (!pipe) 2623ac9391daSGuenter Roeck return -ENOMEM; 2624ac9391daSGuenter Roeck 2625ac9391daSGuenter Roeck params = devm_kzalloc(dev, sizeof(*params), GFP_KERNEL); 2626ac9391daSGuenter Roeck if (!params) 2627ac9391daSGuenter Roeck return -ENOMEM; 2628ac9391daSGuenter Roeck 2629ac9391daSGuenter Roeck pipe->ppl_id = dfw_pipe->pipe_id; 2630ac9391daSGuenter Roeck pipe->memory_pages = dfw_pipe->memory_pages; 2631ac9391daSGuenter Roeck pipe->pipe_priority = dfw_pipe->pipe_priority; 2632ac9391daSGuenter Roeck pipe->conn_type = dfw_pipe->conn_type; 2633ac9391daSGuenter Roeck pipe->state = SKL_PIPE_INVALID; 2634ac9391daSGuenter Roeck pipe->p_params = params; 2635ac9391daSGuenter Roeck INIT_LIST_HEAD(&pipe->w_list); 2636ac9391daSGuenter Roeck 2637ac9391daSGuenter Roeck ppl->pipe = pipe; 2638ac9391daSGuenter Roeck list_add(&ppl->node, &skl->ppl_list); 2639ac9391daSGuenter Roeck 2640ac9391daSGuenter Roeck mconfig->pipe = pipe; 2641ac9391daSGuenter Roeck 2642ac9391daSGuenter Roeck return 0; 2643ac9391daSGuenter Roeck } 2644ac9391daSGuenter Roeck 2645ac9391daSGuenter Roeck static void skl_fill_module_pin_info_v4(struct skl_dfw_v4_module_pin *dfw_pin, 2646ac9391daSGuenter Roeck struct skl_module_pin *m_pin, 2647ac9391daSGuenter Roeck bool is_dynamic, int max_pin) 2648ac9391daSGuenter Roeck { 2649ac9391daSGuenter Roeck int i; 2650ac9391daSGuenter Roeck 2651ac9391daSGuenter Roeck for (i = 0; i < max_pin; i++) { 2652ac9391daSGuenter Roeck m_pin[i].id.module_id = dfw_pin[i].module_id; 2653ac9391daSGuenter Roeck m_pin[i].id.instance_id = dfw_pin[i].instance_id; 2654ac9391daSGuenter Roeck m_pin[i].in_use = false; 2655ac9391daSGuenter Roeck m_pin[i].is_dynamic = is_dynamic; 2656ac9391daSGuenter Roeck m_pin[i].pin_state = SKL_PIN_UNBIND; 2657ac9391daSGuenter Roeck } 2658ac9391daSGuenter Roeck } 2659ac9391daSGuenter Roeck 2660ac9391daSGuenter Roeck static void skl_tplg_fill_fmt_v4(struct skl_module_pin_fmt *dst_fmt, 2661ac9391daSGuenter Roeck struct skl_dfw_v4_module_fmt *src_fmt, 2662ac9391daSGuenter Roeck int pins) 2663ac9391daSGuenter Roeck { 2664ac9391daSGuenter Roeck int i; 2665ac9391daSGuenter Roeck 2666ac9391daSGuenter Roeck for (i = 0; i < pins; i++) { 2667ac9391daSGuenter Roeck dst_fmt[i].fmt.channels = src_fmt[i].channels; 2668ac9391daSGuenter Roeck dst_fmt[i].fmt.s_freq = src_fmt[i].freq; 2669ac9391daSGuenter Roeck dst_fmt[i].fmt.bit_depth = src_fmt[i].bit_depth; 2670ac9391daSGuenter Roeck dst_fmt[i].fmt.valid_bit_depth = src_fmt[i].valid_bit_depth; 2671ac9391daSGuenter Roeck dst_fmt[i].fmt.ch_cfg = src_fmt[i].ch_cfg; 2672ac9391daSGuenter Roeck dst_fmt[i].fmt.ch_map = src_fmt[i].ch_map; 2673ac9391daSGuenter Roeck dst_fmt[i].fmt.interleaving_style = 2674ac9391daSGuenter Roeck src_fmt[i].interleaving_style; 2675ac9391daSGuenter Roeck dst_fmt[i].fmt.sample_type = src_fmt[i].sample_type; 2676ac9391daSGuenter Roeck } 2677ac9391daSGuenter Roeck } 2678ac9391daSGuenter Roeck 2679ac9391daSGuenter Roeck static int skl_tplg_get_pvt_data_v4(struct snd_soc_tplg_dapm_widget *tplg_w, 2680bcc2a2dcSCezary Rojewski struct skl_dev *skl, struct device *dev, 2681ac9391daSGuenter Roeck struct skl_module_cfg *mconfig) 2682ac9391daSGuenter Roeck { 2683ac9391daSGuenter Roeck struct skl_dfw_v4_module *dfw = 2684ac9391daSGuenter Roeck (struct skl_dfw_v4_module *)tplg_w->priv.data; 2685ac9391daSGuenter Roeck int ret; 2686ac9391daSGuenter Roeck 2687ac9391daSGuenter Roeck dev_dbg(dev, "Parsing Skylake v4 widget topology data\n"); 2688ac9391daSGuenter Roeck 2689ac9391daSGuenter Roeck ret = guid_parse(dfw->uuid, (guid_t *)mconfig->guid); 2690ac9391daSGuenter Roeck if (ret) 2691ac9391daSGuenter Roeck return ret; 2692ac9391daSGuenter Roeck mconfig->id.module_id = -1; 2693ac9391daSGuenter Roeck mconfig->id.instance_id = dfw->instance_id; 269484b71067SCezary Rojewski mconfig->module->resources[0].cpc = dfw->max_mcps / 1000; 2695ac9391daSGuenter Roeck mconfig->module->resources[0].ibs = dfw->ibs; 2696ac9391daSGuenter Roeck mconfig->module->resources[0].obs = dfw->obs; 2697ac9391daSGuenter Roeck mconfig->core_id = dfw->core_id; 2698ac9391daSGuenter Roeck mconfig->module->max_input_pins = dfw->max_in_queue; 2699ac9391daSGuenter Roeck mconfig->module->max_output_pins = dfw->max_out_queue; 2700ac9391daSGuenter Roeck mconfig->module->loadable = dfw->is_loadable; 2701ac9391daSGuenter Roeck skl_tplg_fill_fmt_v4(mconfig->module->formats[0].inputs, dfw->in_fmt, 2702ac9391daSGuenter Roeck MAX_IN_QUEUE); 2703ac9391daSGuenter Roeck skl_tplg_fill_fmt_v4(mconfig->module->formats[0].outputs, dfw->out_fmt, 2704ac9391daSGuenter Roeck MAX_OUT_QUEUE); 2705ac9391daSGuenter Roeck 2706ac9391daSGuenter Roeck mconfig->params_fixup = dfw->params_fixup; 2707ac9391daSGuenter Roeck mconfig->converter = dfw->converter; 2708ac9391daSGuenter Roeck mconfig->m_type = dfw->module_type; 2709ac9391daSGuenter Roeck mconfig->vbus_id = dfw->vbus_id; 2710ac9391daSGuenter Roeck mconfig->module->resources[0].is_pages = dfw->mem_pages; 2711ac9391daSGuenter Roeck 2712ac9391daSGuenter Roeck ret = skl_tplg_add_pipe_v4(dev, mconfig, skl, &dfw->pipe); 2713ac9391daSGuenter Roeck if (ret) 2714ac9391daSGuenter Roeck return ret; 2715ac9391daSGuenter Roeck 2716ac9391daSGuenter Roeck mconfig->dev_type = dfw->dev_type; 2717ac9391daSGuenter Roeck mconfig->hw_conn_type = dfw->hw_conn_type; 2718ac9391daSGuenter Roeck mconfig->time_slot = dfw->time_slot; 2719ac9391daSGuenter Roeck mconfig->formats_config.caps_size = dfw->caps.caps_size; 2720ac9391daSGuenter Roeck 2721a86854d0SKees Cook mconfig->m_in_pin = devm_kcalloc(dev, 2722a86854d0SKees Cook MAX_IN_QUEUE, sizeof(*mconfig->m_in_pin), 2723ac9391daSGuenter Roeck GFP_KERNEL); 2724ac9391daSGuenter Roeck if (!mconfig->m_in_pin) 2725ac9391daSGuenter Roeck return -ENOMEM; 2726ac9391daSGuenter Roeck 2727a86854d0SKees Cook mconfig->m_out_pin = devm_kcalloc(dev, 2728a86854d0SKees Cook MAX_OUT_QUEUE, sizeof(*mconfig->m_out_pin), 2729ac9391daSGuenter Roeck GFP_KERNEL); 2730ac9391daSGuenter Roeck if (!mconfig->m_out_pin) 2731ac9391daSGuenter Roeck return -ENOMEM; 2732ac9391daSGuenter Roeck 2733ac9391daSGuenter Roeck skl_fill_module_pin_info_v4(dfw->in_pin, mconfig->m_in_pin, 2734ac9391daSGuenter Roeck dfw->is_dynamic_in_pin, 2735ac9391daSGuenter Roeck mconfig->module->max_input_pins); 2736ac9391daSGuenter Roeck skl_fill_module_pin_info_v4(dfw->out_pin, mconfig->m_out_pin, 2737ac9391daSGuenter Roeck dfw->is_dynamic_out_pin, 2738ac9391daSGuenter Roeck mconfig->module->max_output_pins); 2739ac9391daSGuenter Roeck 2740ac9391daSGuenter Roeck if (mconfig->formats_config.caps_size) { 2741ac9391daSGuenter Roeck mconfig->formats_config.set_params = dfw->caps.set_params; 2742ac9391daSGuenter Roeck mconfig->formats_config.param_id = dfw->caps.param_id; 2743ac9391daSGuenter Roeck mconfig->formats_config.caps = 2744ac9391daSGuenter Roeck devm_kzalloc(dev, mconfig->formats_config.caps_size, 2745ac9391daSGuenter Roeck GFP_KERNEL); 2746ac9391daSGuenter Roeck if (!mconfig->formats_config.caps) 2747ac9391daSGuenter Roeck return -ENOMEM; 2748ac9391daSGuenter Roeck memcpy(mconfig->formats_config.caps, dfw->caps.caps, 2749ac9391daSGuenter Roeck dfw->caps.caps_size); 2750ac9391daSGuenter Roeck } 2751ac9391daSGuenter Roeck 2752ac9391daSGuenter Roeck return 0; 2753ac9391daSGuenter Roeck } 2754ac9391daSGuenter Roeck 27556277e832SShreyas NC /* 27566277e832SShreyas NC * Parse the private data for the token and corresponding value. 27576277e832SShreyas NC * The private data can have multiple data blocks. So, a data block 27586277e832SShreyas NC * is preceded by a descriptor for number of blocks and a descriptor 27596277e832SShreyas NC * for the type and size of the suceeding data block. 27606277e832SShreyas NC */ 27616277e832SShreyas NC static int skl_tplg_get_pvt_data(struct snd_soc_tplg_dapm_widget *tplg_w, 2762bcc2a2dcSCezary Rojewski struct skl_dev *skl, struct device *dev, 27636277e832SShreyas NC struct skl_module_cfg *mconfig) 27646277e832SShreyas NC { 27656277e832SShreyas NC struct snd_soc_tplg_vendor_array *array; 27666277e832SShreyas NC int num_blocks, block_size = 0, block_type, off = 0; 27676277e832SShreyas NC char *data; 27686277e832SShreyas NC int ret; 27696277e832SShreyas NC 2770ac9391daSGuenter Roeck /* 2771ac9391daSGuenter Roeck * v4 configuration files have a valid UUID at the start of 2772ac9391daSGuenter Roeck * the widget's private data. 2773ac9391daSGuenter Roeck */ 2774ac9391daSGuenter Roeck if (uuid_is_valid((char *)tplg_w->priv.data)) 2775ac9391daSGuenter Roeck return skl_tplg_get_pvt_data_v4(tplg_w, skl, dev, mconfig); 2776ac9391daSGuenter Roeck 27776277e832SShreyas NC /* Read the NUM_DATA_BLOCKS descriptor */ 27786277e832SShreyas NC array = (struct snd_soc_tplg_vendor_array *)tplg_w->priv.data; 27796277e832SShreyas NC ret = skl_tplg_get_desc_blocks(dev, array); 27806277e832SShreyas NC if (ret < 0) 27816277e832SShreyas NC return ret; 27826277e832SShreyas NC num_blocks = ret; 27836277e832SShreyas NC 27846277e832SShreyas NC off += array->size; 27856277e832SShreyas NC /* Read the BLOCK_TYPE and BLOCK_SIZE descriptor */ 27866277e832SShreyas NC while (num_blocks > 0) { 2787133e6e5cSShreyas NC array = (struct snd_soc_tplg_vendor_array *) 2788133e6e5cSShreyas NC (tplg_w->priv.data + off); 2789133e6e5cSShreyas NC 27906277e832SShreyas NC ret = skl_tplg_get_desc_blocks(dev, array); 27916277e832SShreyas NC 27926277e832SShreyas NC if (ret < 0) 27936277e832SShreyas NC return ret; 27946277e832SShreyas NC block_type = ret; 27956277e832SShreyas NC off += array->size; 27966277e832SShreyas NC 27976277e832SShreyas NC array = (struct snd_soc_tplg_vendor_array *) 27986277e832SShreyas NC (tplg_w->priv.data + off); 27996277e832SShreyas NC 28006277e832SShreyas NC ret = skl_tplg_get_desc_blocks(dev, array); 28016277e832SShreyas NC 28026277e832SShreyas NC if (ret < 0) 28036277e832SShreyas NC return ret; 28046277e832SShreyas NC block_size = ret; 28056277e832SShreyas NC off += array->size; 28066277e832SShreyas NC 28076277e832SShreyas NC array = (struct snd_soc_tplg_vendor_array *) 28086277e832SShreyas NC (tplg_w->priv.data + off); 28096277e832SShreyas NC 28106277e832SShreyas NC data = (tplg_w->priv.data + off); 28116277e832SShreyas NC 28126277e832SShreyas NC if (block_type == SKL_TYPE_TUPLE) { 28136277e832SShreyas NC ret = skl_tplg_get_tokens(dev, data, 28146277e832SShreyas NC skl, mconfig, block_size); 28156277e832SShreyas NC 28166277e832SShreyas NC if (ret < 0) 28176277e832SShreyas NC return ret; 28186277e832SShreyas NC 28196277e832SShreyas NC --num_blocks; 28206277e832SShreyas NC } else { 28216277e832SShreyas NC if (mconfig->formats_config.caps_size > 0) 28226277e832SShreyas NC memcpy(mconfig->formats_config.caps, data, 28236277e832SShreyas NC mconfig->formats_config.caps_size); 28246277e832SShreyas NC --num_blocks; 2825133e6e5cSShreyas NC ret = mconfig->formats_config.caps_size; 28266277e832SShreyas NC } 2827133e6e5cSShreyas NC off += ret; 28286277e832SShreyas NC } 28296277e832SShreyas NC 28306277e832SShreyas NC return 0; 28314cd9899fSHardik T Shah } 28324cd9899fSHardik T Shah 283356b03b4cSKuninori Morimoto static void skl_clear_pin_config(struct snd_soc_component *component, 2834fe3f4442SDharageswari R struct snd_soc_dapm_widget *w) 2835fe3f4442SDharageswari R { 2836fe3f4442SDharageswari R int i; 2837fe3f4442SDharageswari R struct skl_module_cfg *mconfig; 2838fe3f4442SDharageswari R struct skl_pipe *pipe; 2839fe3f4442SDharageswari R 284056b03b4cSKuninori Morimoto if (!strncmp(w->dapm->component->name, component->name, 284156b03b4cSKuninori Morimoto strlen(component->name))) { 2842fe3f4442SDharageswari R mconfig = w->priv; 2843fe3f4442SDharageswari R pipe = mconfig->pipe; 2844f6fa56e2SRamesh Babu for (i = 0; i < mconfig->module->max_input_pins; i++) { 2845fe3f4442SDharageswari R mconfig->m_in_pin[i].in_use = false; 2846fe3f4442SDharageswari R mconfig->m_in_pin[i].pin_state = SKL_PIN_UNBIND; 2847fe3f4442SDharageswari R } 2848f6fa56e2SRamesh Babu for (i = 0; i < mconfig->module->max_output_pins; i++) { 2849fe3f4442SDharageswari R mconfig->m_out_pin[i].in_use = false; 2850fe3f4442SDharageswari R mconfig->m_out_pin[i].pin_state = SKL_PIN_UNBIND; 2851fe3f4442SDharageswari R } 2852fe3f4442SDharageswari R pipe->state = SKL_PIPE_INVALID; 2853fe3f4442SDharageswari R mconfig->m_state = SKL_MODULE_UNINIT; 2854fe3f4442SDharageswari R } 2855fe3f4442SDharageswari R } 2856fe3f4442SDharageswari R 2857bcc2a2dcSCezary Rojewski void skl_cleanup_resources(struct skl_dev *skl) 2858fe3f4442SDharageswari R { 285956b03b4cSKuninori Morimoto struct snd_soc_component *soc_component = skl->component; 2860fe3f4442SDharageswari R struct snd_soc_dapm_widget *w; 2861fe3f4442SDharageswari R struct snd_soc_card *card; 2862fe3f4442SDharageswari R 286356b03b4cSKuninori Morimoto if (soc_component == NULL) 2864fe3f4442SDharageswari R return; 2865fe3f4442SDharageswari R 286656b03b4cSKuninori Morimoto card = soc_component->card; 2867fe3f4442SDharageswari R if (!card || !card->instantiated) 2868fe3f4442SDharageswari R return; 2869fe3f4442SDharageswari R 2870fe3f4442SDharageswari R list_for_each_entry(w, &card->widgets, list) { 2871bcc2a2dcSCezary Rojewski if (is_skl_dsp_widget_type(w, skl->dev) && w->priv != NULL) 287256b03b4cSKuninori Morimoto skl_clear_pin_config(soc_component, w); 2873fe3f4442SDharageswari R } 2874fe3f4442SDharageswari R 2875bcc2a2dcSCezary Rojewski skl_clear_module_cnt(skl->dsp); 2876fe3f4442SDharageswari R } 2877fe3f4442SDharageswari R 28783af36706SVinod Koul /* 28793af36706SVinod Koul * Topology core widget load callback 28803af36706SVinod Koul * 28813af36706SVinod Koul * This is used to save the private data for each widget which gives 28823af36706SVinod Koul * information to the driver about module and pipeline parameters which DSP 28833af36706SVinod Koul * FW expects like ids, resource values, formats etc 28843af36706SVinod Koul */ 2885c60b613aSLiam Girdwood static int skl_tplg_widget_load(struct snd_soc_component *cmpnt, int index, 28863af36706SVinod Koul struct snd_soc_dapm_widget *w, 28873af36706SVinod Koul struct snd_soc_tplg_dapm_widget *tplg_w) 28883af36706SVinod Koul { 28893af36706SVinod Koul int ret; 289076f56faeSRakesh Ughreja struct hdac_bus *bus = snd_soc_component_get_drvdata(cmpnt); 2891bcc2a2dcSCezary Rojewski struct skl_dev *skl = bus_to_skl(bus); 28923af36706SVinod Koul struct skl_module_cfg *mconfig; 28933af36706SVinod Koul 28943af36706SVinod Koul if (!tplg_w->priv.size) 28953af36706SVinod Koul goto bind_event; 28963af36706SVinod Koul 28973af36706SVinod Koul mconfig = devm_kzalloc(bus->dev, sizeof(*mconfig), GFP_KERNEL); 28983af36706SVinod Koul 28993af36706SVinod Koul if (!mconfig) 29003af36706SVinod Koul return -ENOMEM; 29013af36706SVinod Koul 2902f6fa56e2SRamesh Babu if (skl->nr_modules == 0) { 2903f6fa56e2SRamesh Babu mconfig->module = devm_kzalloc(bus->dev, 2904f6fa56e2SRamesh Babu sizeof(*mconfig->module), GFP_KERNEL); 2905f6fa56e2SRamesh Babu if (!mconfig->module) 2906f6fa56e2SRamesh Babu return -ENOMEM; 2907f6fa56e2SRamesh Babu } 2908f6fa56e2SRamesh Babu 29093af36706SVinod Koul w->priv = mconfig; 291009305da9SShreyas NC 2911b7c50555SVinod Koul /* 2912b7c50555SVinod Koul * module binary can be loaded later, so set it to query when 2913b7c50555SVinod Koul * module is load for a use case 2914b7c50555SVinod Koul */ 2915b7c50555SVinod Koul mconfig->id.module_id = -1; 29164cd9899fSHardik T Shah 29176277e832SShreyas NC /* Parse private data for tuples */ 29186277e832SShreyas NC ret = skl_tplg_get_pvt_data(tplg_w, skl, bus->dev, mconfig); 29196277e832SShreyas NC if (ret < 0) 29206277e832SShreyas NC return ret; 2921d14700a0SVinod Koul 2922d14700a0SVinod Koul skl_debug_init_module(skl->debugfs, w, mconfig); 2923d14700a0SVinod Koul 29243af36706SVinod Koul bind_event: 29253af36706SVinod Koul if (tplg_w->event_type == 0) { 29263373f716SVinod Koul dev_dbg(bus->dev, "ASoC: No event handler required\n"); 29273af36706SVinod Koul return 0; 29283af36706SVinod Koul } 29293af36706SVinod Koul 29303af36706SVinod Koul ret = snd_soc_tplg_widget_bind_event(w, skl_tplg_widget_ops, 2931b663a8c5SJeeja KP ARRAY_SIZE(skl_tplg_widget_ops), 2932b663a8c5SJeeja KP tplg_w->event_type); 29333af36706SVinod Koul 29343af36706SVinod Koul if (ret) { 29353af36706SVinod Koul dev_err(bus->dev, "%s: No matching event handlers found for %d\n", 29363af36706SVinod Koul __func__, tplg_w->event_type); 29373af36706SVinod Koul return -EINVAL; 29383af36706SVinod Koul } 29393af36706SVinod Koul 29403af36706SVinod Koul return 0; 29413af36706SVinod Koul } 29423af36706SVinod Koul 2943140adfbaSJeeja KP static int skl_init_algo_data(struct device *dev, struct soc_bytes_ext *be, 2944140adfbaSJeeja KP struct snd_soc_tplg_bytes_control *bc) 2945140adfbaSJeeja KP { 2946140adfbaSJeeja KP struct skl_algo_data *ac; 2947140adfbaSJeeja KP struct skl_dfw_algo_data *dfw_ac = 2948140adfbaSJeeja KP (struct skl_dfw_algo_data *)bc->priv.data; 2949140adfbaSJeeja KP 2950140adfbaSJeeja KP ac = devm_kzalloc(dev, sizeof(*ac), GFP_KERNEL); 2951140adfbaSJeeja KP if (!ac) 2952140adfbaSJeeja KP return -ENOMEM; 2953140adfbaSJeeja KP 2954140adfbaSJeeja KP /* Fill private data */ 2955140adfbaSJeeja KP ac->max = dfw_ac->max; 2956140adfbaSJeeja KP ac->param_id = dfw_ac->param_id; 2957140adfbaSJeeja KP ac->set_params = dfw_ac->set_params; 29580d682104SDharageswari R ac->size = dfw_ac->max; 2959140adfbaSJeeja KP 2960140adfbaSJeeja KP if (ac->max) { 2961431b67c2SPierre-Louis Bossart ac->params = devm_kzalloc(dev, ac->max, GFP_KERNEL); 2962140adfbaSJeeja KP if (!ac->params) 2963140adfbaSJeeja KP return -ENOMEM; 2964140adfbaSJeeja KP 2965140adfbaSJeeja KP memcpy(ac->params, dfw_ac->params, ac->max); 2966140adfbaSJeeja KP } 2967140adfbaSJeeja KP 2968140adfbaSJeeja KP be->dobj.private = ac; 2969140adfbaSJeeja KP return 0; 2970140adfbaSJeeja KP } 2971140adfbaSJeeja KP 29727a1b749bSDharageswari R static int skl_init_enum_data(struct device *dev, struct soc_enum *se, 29737a1b749bSDharageswari R struct snd_soc_tplg_enum_control *ec) 29747a1b749bSDharageswari R { 29757a1b749bSDharageswari R 29767a1b749bSDharageswari R void *data; 29777a1b749bSDharageswari R 29787a1b749bSDharageswari R if (ec->priv.size) { 29797a1b749bSDharageswari R data = devm_kzalloc(dev, sizeof(ec->priv.size), GFP_KERNEL); 29807a1b749bSDharageswari R if (!data) 29817a1b749bSDharageswari R return -ENOMEM; 29827a1b749bSDharageswari R memcpy(data, ec->priv.data, ec->priv.size); 29837a1b749bSDharageswari R se->dobj.private = data; 29847a1b749bSDharageswari R } 29857a1b749bSDharageswari R 29867a1b749bSDharageswari R return 0; 29877a1b749bSDharageswari R 29887a1b749bSDharageswari R } 29897a1b749bSDharageswari R 2990140adfbaSJeeja KP static int skl_tplg_control_load(struct snd_soc_component *cmpnt, 2991c60b613aSLiam Girdwood int index, 2992140adfbaSJeeja KP struct snd_kcontrol_new *kctl, 2993140adfbaSJeeja KP struct snd_soc_tplg_ctl_hdr *hdr) 2994140adfbaSJeeja KP { 2995140adfbaSJeeja KP struct soc_bytes_ext *sb; 2996140adfbaSJeeja KP struct snd_soc_tplg_bytes_control *tplg_bc; 29977a1b749bSDharageswari R struct snd_soc_tplg_enum_control *tplg_ec; 299876f56faeSRakesh Ughreja struct hdac_bus *bus = snd_soc_component_get_drvdata(cmpnt); 29997a1b749bSDharageswari R struct soc_enum *se; 3000140adfbaSJeeja KP 3001140adfbaSJeeja KP switch (hdr->ops.info) { 3002140adfbaSJeeja KP case SND_SOC_TPLG_CTL_BYTES: 3003140adfbaSJeeja KP tplg_bc = container_of(hdr, 3004140adfbaSJeeja KP struct snd_soc_tplg_bytes_control, hdr); 3005140adfbaSJeeja KP if (kctl->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { 3006140adfbaSJeeja KP sb = (struct soc_bytes_ext *)kctl->private_value; 3007140adfbaSJeeja KP if (tplg_bc->priv.size) 3008140adfbaSJeeja KP return skl_init_algo_data( 3009140adfbaSJeeja KP bus->dev, sb, tplg_bc); 3010140adfbaSJeeja KP } 3011140adfbaSJeeja KP break; 3012140adfbaSJeeja KP 30137a1b749bSDharageswari R case SND_SOC_TPLG_CTL_ENUM: 30147a1b749bSDharageswari R tplg_ec = container_of(hdr, 30157a1b749bSDharageswari R struct snd_soc_tplg_enum_control, hdr); 30167a1b749bSDharageswari R if (kctl->access & SNDRV_CTL_ELEM_ACCESS_READWRITE) { 30177a1b749bSDharageswari R se = (struct soc_enum *)kctl->private_value; 30187a1b749bSDharageswari R if (tplg_ec->priv.size) 30197a1b749bSDharageswari R return skl_init_enum_data(bus->dev, se, 30207a1b749bSDharageswari R tplg_ec); 30217a1b749bSDharageswari R } 30227a1b749bSDharageswari R break; 30237a1b749bSDharageswari R 3024140adfbaSJeeja KP default: 30254362934aSNaveen Manohar dev_dbg(bus->dev, "Control load not supported %d:%d:%d\n", 3026140adfbaSJeeja KP hdr->ops.get, hdr->ops.put, hdr->ops.info); 3027140adfbaSJeeja KP break; 3028140adfbaSJeeja KP } 3029140adfbaSJeeja KP 3030140adfbaSJeeja KP return 0; 3031140adfbaSJeeja KP } 3032140adfbaSJeeja KP 3033541070ceSShreyas NC static int skl_tplg_fill_str_mfest_tkn(struct device *dev, 3034541070ceSShreyas NC struct snd_soc_tplg_vendor_string_elem *str_elem, 3035bcc2a2dcSCezary Rojewski struct skl_dev *skl) 3036541070ceSShreyas NC { 3037541070ceSShreyas NC int tkn_count = 0; 3038541070ceSShreyas NC static int ref_count; 3039541070ceSShreyas NC 3040541070ceSShreyas NC switch (str_elem->token) { 3041541070ceSShreyas NC case SKL_TKN_STR_LIB_NAME: 3042bcc2a2dcSCezary Rojewski if (ref_count > skl->lib_count - 1) { 3043541070ceSShreyas NC ref_count = 0; 3044541070ceSShreyas NC return -EINVAL; 3045541070ceSShreyas NC } 3046541070ceSShreyas NC 3047bcc2a2dcSCezary Rojewski strncpy(skl->lib_info[ref_count].name, 3048eee0e16fSJeeja KP str_elem->string, 3049bcc2a2dcSCezary Rojewski ARRAY_SIZE(skl->lib_info[ref_count].name)); 3050541070ceSShreyas NC ref_count++; 3051541070ceSShreyas NC break; 3052541070ceSShreyas NC 3053541070ceSShreyas NC default: 3054ecd286a9SColin Ian King dev_err(dev, "Not a string token %d\n", str_elem->token); 3055541070ceSShreyas NC break; 3056541070ceSShreyas NC } 3057db6ed55dSShreyas NC tkn_count++; 3058541070ceSShreyas NC 3059541070ceSShreyas NC return tkn_count; 3060541070ceSShreyas NC } 3061541070ceSShreyas NC 3062541070ceSShreyas NC static int skl_tplg_get_str_tkn(struct device *dev, 3063541070ceSShreyas NC struct snd_soc_tplg_vendor_array *array, 3064bcc2a2dcSCezary Rojewski struct skl_dev *skl) 3065541070ceSShreyas NC { 3066541070ceSShreyas NC int tkn_count = 0, ret; 3067541070ceSShreyas NC struct snd_soc_tplg_vendor_string_elem *str_elem; 3068541070ceSShreyas NC 3069541070ceSShreyas NC str_elem = (struct snd_soc_tplg_vendor_string_elem *)array->value; 3070541070ceSShreyas NC while (tkn_count < array->num_elems) { 3071eee0e16fSJeeja KP ret = skl_tplg_fill_str_mfest_tkn(dev, str_elem, skl); 3072541070ceSShreyas NC str_elem++; 3073541070ceSShreyas NC 3074541070ceSShreyas NC if (ret < 0) 3075541070ceSShreyas NC return ret; 3076541070ceSShreyas NC 3077541070ceSShreyas NC tkn_count = tkn_count + ret; 3078541070ceSShreyas NC } 3079541070ceSShreyas NC 3080541070ceSShreyas NC return tkn_count; 3081541070ceSShreyas NC } 3082541070ceSShreyas NC 3083db6ed55dSShreyas NC static int skl_tplg_manifest_fill_fmt(struct device *dev, 3084db6ed55dSShreyas NC struct skl_module_iface *fmt, 3085db6ed55dSShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem, 3086db6ed55dSShreyas NC u32 dir, int fmt_idx) 3087db6ed55dSShreyas NC { 3088db6ed55dSShreyas NC struct skl_module_pin_fmt *dst_fmt; 3089db6ed55dSShreyas NC struct skl_module_fmt *mod_fmt; 3090db6ed55dSShreyas NC int ret; 3091db6ed55dSShreyas NC 3092db6ed55dSShreyas NC if (!fmt) 3093db6ed55dSShreyas NC return -EINVAL; 3094db6ed55dSShreyas NC 3095db6ed55dSShreyas NC switch (dir) { 3096db6ed55dSShreyas NC case SKL_DIR_IN: 3097db6ed55dSShreyas NC dst_fmt = &fmt->inputs[fmt_idx]; 3098db6ed55dSShreyas NC break; 3099db6ed55dSShreyas NC 3100db6ed55dSShreyas NC case SKL_DIR_OUT: 3101db6ed55dSShreyas NC dst_fmt = &fmt->outputs[fmt_idx]; 3102db6ed55dSShreyas NC break; 3103db6ed55dSShreyas NC 3104db6ed55dSShreyas NC default: 3105db6ed55dSShreyas NC dev_err(dev, "Invalid direction: %d\n", dir); 3106db6ed55dSShreyas NC return -EINVAL; 3107db6ed55dSShreyas NC } 3108db6ed55dSShreyas NC 3109db6ed55dSShreyas NC mod_fmt = &dst_fmt->fmt; 3110db6ed55dSShreyas NC 3111db6ed55dSShreyas NC switch (tkn_elem->token) { 3112db6ed55dSShreyas NC case SKL_TKN_MM_U32_INTF_PIN_ID: 3113db6ed55dSShreyas NC dst_fmt->id = tkn_elem->value; 3114db6ed55dSShreyas NC break; 3115db6ed55dSShreyas NC 3116db6ed55dSShreyas NC default: 3117db6ed55dSShreyas NC ret = skl_tplg_fill_fmt(dev, mod_fmt, tkn_elem->token, 3118db6ed55dSShreyas NC tkn_elem->value); 3119db6ed55dSShreyas NC if (ret < 0) 3120db6ed55dSShreyas NC return ret; 3121db6ed55dSShreyas NC break; 3122db6ed55dSShreyas NC } 3123db6ed55dSShreyas NC 3124db6ed55dSShreyas NC return 0; 3125db6ed55dSShreyas NC } 3126db6ed55dSShreyas NC 3127db6ed55dSShreyas NC static int skl_tplg_fill_mod_info(struct device *dev, 3128db6ed55dSShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem, 3129db6ed55dSShreyas NC struct skl_module *mod) 3130db6ed55dSShreyas NC { 3131db6ed55dSShreyas NC 3132db6ed55dSShreyas NC if (!mod) 3133db6ed55dSShreyas NC return -EINVAL; 3134db6ed55dSShreyas NC 3135db6ed55dSShreyas NC switch (tkn_elem->token) { 3136db6ed55dSShreyas NC case SKL_TKN_U8_IN_PIN_TYPE: 3137db6ed55dSShreyas NC mod->input_pin_type = tkn_elem->value; 3138db6ed55dSShreyas NC break; 3139db6ed55dSShreyas NC 3140db6ed55dSShreyas NC case SKL_TKN_U8_OUT_PIN_TYPE: 3141db6ed55dSShreyas NC mod->output_pin_type = tkn_elem->value; 3142db6ed55dSShreyas NC break; 3143db6ed55dSShreyas NC 3144db6ed55dSShreyas NC case SKL_TKN_U8_IN_QUEUE_COUNT: 3145db6ed55dSShreyas NC mod->max_input_pins = tkn_elem->value; 3146db6ed55dSShreyas NC break; 3147db6ed55dSShreyas NC 3148db6ed55dSShreyas NC case SKL_TKN_U8_OUT_QUEUE_COUNT: 3149db6ed55dSShreyas NC mod->max_output_pins = tkn_elem->value; 3150db6ed55dSShreyas NC break; 3151db6ed55dSShreyas NC 3152db6ed55dSShreyas NC case SKL_TKN_MM_U8_NUM_RES: 3153db6ed55dSShreyas NC mod->nr_resources = tkn_elem->value; 3154db6ed55dSShreyas NC break; 3155db6ed55dSShreyas NC 3156db6ed55dSShreyas NC case SKL_TKN_MM_U8_NUM_INTF: 3157db6ed55dSShreyas NC mod->nr_interfaces = tkn_elem->value; 3158db6ed55dSShreyas NC break; 3159db6ed55dSShreyas NC 3160db6ed55dSShreyas NC default: 3161db6ed55dSShreyas NC dev_err(dev, "Invalid mod info token %d", tkn_elem->token); 3162db6ed55dSShreyas NC return -EINVAL; 3163db6ed55dSShreyas NC } 3164db6ed55dSShreyas NC 3165db6ed55dSShreyas NC return 0; 3166db6ed55dSShreyas NC } 3167db6ed55dSShreyas NC 3168db6ed55dSShreyas NC 3169541070ceSShreyas NC static int skl_tplg_get_int_tkn(struct device *dev, 3170541070ceSShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem, 3171bcc2a2dcSCezary Rojewski struct skl_dev *skl) 3172541070ceSShreyas NC { 3173d00cc2f1SGustavo A. R. Silva int tkn_count = 0, ret; 3174db6ed55dSShreyas NC static int mod_idx, res_val_idx, intf_val_idx, dir, pin_idx; 3175db6ed55dSShreyas NC struct skl_module_res *res = NULL; 3176db6ed55dSShreyas NC struct skl_module_iface *fmt = NULL; 3177db6ed55dSShreyas NC struct skl_module *mod = NULL; 317843762355SPradeep Tewani static struct skl_astate_param *astate_table; 317943762355SPradeep Tewani static int astate_cfg_idx, count; 3180db6ed55dSShreyas NC int i; 3181d00cc2f1SGustavo A. R. Silva size_t size; 3182db6ed55dSShreyas NC 3183db6ed55dSShreyas NC if (skl->modules) { 3184db6ed55dSShreyas NC mod = skl->modules[mod_idx]; 3185db6ed55dSShreyas NC res = &mod->resources[res_val_idx]; 3186db6ed55dSShreyas NC fmt = &mod->formats[intf_val_idx]; 3187db6ed55dSShreyas NC } 3188541070ceSShreyas NC 3189541070ceSShreyas NC switch (tkn_elem->token) { 3190541070ceSShreyas NC case SKL_TKN_U32_LIB_COUNT: 3191bcc2a2dcSCezary Rojewski skl->lib_count = tkn_elem->value; 3192db6ed55dSShreyas NC break; 3193db6ed55dSShreyas NC 3194db6ed55dSShreyas NC case SKL_TKN_U8_NUM_MOD: 3195db6ed55dSShreyas NC skl->nr_modules = tkn_elem->value; 3196db6ed55dSShreyas NC skl->modules = devm_kcalloc(dev, skl->nr_modules, 3197db6ed55dSShreyas NC sizeof(*skl->modules), GFP_KERNEL); 3198db6ed55dSShreyas NC if (!skl->modules) 3199db6ed55dSShreyas NC return -ENOMEM; 3200db6ed55dSShreyas NC 3201db6ed55dSShreyas NC for (i = 0; i < skl->nr_modules; i++) { 3202db6ed55dSShreyas NC skl->modules[i] = devm_kzalloc(dev, 3203db6ed55dSShreyas NC sizeof(struct skl_module), GFP_KERNEL); 3204db6ed55dSShreyas NC if (!skl->modules[i]) 3205db6ed55dSShreyas NC return -ENOMEM; 3206db6ed55dSShreyas NC } 3207db6ed55dSShreyas NC break; 3208db6ed55dSShreyas NC 3209db6ed55dSShreyas NC case SKL_TKN_MM_U8_MOD_IDX: 3210db6ed55dSShreyas NC mod_idx = tkn_elem->value; 3211db6ed55dSShreyas NC break; 3212db6ed55dSShreyas NC 321343762355SPradeep Tewani case SKL_TKN_U32_ASTATE_COUNT: 321443762355SPradeep Tewani if (astate_table != NULL) { 321543762355SPradeep Tewani dev_err(dev, "More than one entry for A-State count"); 321643762355SPradeep Tewani return -EINVAL; 321743762355SPradeep Tewani } 321843762355SPradeep Tewani 321943762355SPradeep Tewani if (tkn_elem->value > SKL_MAX_ASTATE_CFG) { 322043762355SPradeep Tewani dev_err(dev, "Invalid A-State count %d\n", 322143762355SPradeep Tewani tkn_elem->value); 322243762355SPradeep Tewani return -EINVAL; 322343762355SPradeep Tewani } 322443762355SPradeep Tewani 3225d00cc2f1SGustavo A. R. Silva size = struct_size(skl->cfg.astate_cfg, astate_table, 3226d00cc2f1SGustavo A. R. Silva tkn_elem->value); 322743762355SPradeep Tewani skl->cfg.astate_cfg = devm_kzalloc(dev, size, GFP_KERNEL); 322843762355SPradeep Tewani if (!skl->cfg.astate_cfg) 322943762355SPradeep Tewani return -ENOMEM; 323043762355SPradeep Tewani 323143762355SPradeep Tewani astate_table = skl->cfg.astate_cfg->astate_table; 323243762355SPradeep Tewani count = skl->cfg.astate_cfg->count = tkn_elem->value; 323343762355SPradeep Tewani break; 323443762355SPradeep Tewani 323543762355SPradeep Tewani case SKL_TKN_U32_ASTATE_IDX: 323643762355SPradeep Tewani if (tkn_elem->value >= count) { 323743762355SPradeep Tewani dev_err(dev, "Invalid A-State index %d\n", 323843762355SPradeep Tewani tkn_elem->value); 323943762355SPradeep Tewani return -EINVAL; 324043762355SPradeep Tewani } 324143762355SPradeep Tewani 324243762355SPradeep Tewani astate_cfg_idx = tkn_elem->value; 324343762355SPradeep Tewani break; 324443762355SPradeep Tewani 324543762355SPradeep Tewani case SKL_TKN_U32_ASTATE_KCPS: 324643762355SPradeep Tewani astate_table[astate_cfg_idx].kcps = tkn_elem->value; 324743762355SPradeep Tewani break; 324843762355SPradeep Tewani 324943762355SPradeep Tewani case SKL_TKN_U32_ASTATE_CLK_SRC: 325043762355SPradeep Tewani astate_table[astate_cfg_idx].clk_src = tkn_elem->value; 325143762355SPradeep Tewani break; 325243762355SPradeep Tewani 3253db6ed55dSShreyas NC case SKL_TKN_U8_IN_PIN_TYPE: 3254db6ed55dSShreyas NC case SKL_TKN_U8_OUT_PIN_TYPE: 3255db6ed55dSShreyas NC case SKL_TKN_U8_IN_QUEUE_COUNT: 3256db6ed55dSShreyas NC case SKL_TKN_U8_OUT_QUEUE_COUNT: 3257db6ed55dSShreyas NC case SKL_TKN_MM_U8_NUM_RES: 3258db6ed55dSShreyas NC case SKL_TKN_MM_U8_NUM_INTF: 3259db6ed55dSShreyas NC ret = skl_tplg_fill_mod_info(dev, tkn_elem, mod); 3260db6ed55dSShreyas NC if (ret < 0) 3261db6ed55dSShreyas NC return ret; 3262db6ed55dSShreyas NC break; 3263db6ed55dSShreyas NC 3264db6ed55dSShreyas NC case SKL_TKN_U32_DIR_PIN_COUNT: 3265db6ed55dSShreyas NC dir = tkn_elem->value & SKL_IN_DIR_BIT_MASK; 3266db6ed55dSShreyas NC pin_idx = (tkn_elem->value & SKL_PIN_COUNT_MASK) >> 4; 3267db6ed55dSShreyas NC break; 3268db6ed55dSShreyas NC 3269db6ed55dSShreyas NC case SKL_TKN_MM_U32_RES_ID: 3270db6ed55dSShreyas NC if (!res) 3271db6ed55dSShreyas NC return -EINVAL; 3272db6ed55dSShreyas NC 3273db6ed55dSShreyas NC res->id = tkn_elem->value; 3274db6ed55dSShreyas NC res_val_idx = tkn_elem->value; 3275db6ed55dSShreyas NC break; 3276db6ed55dSShreyas NC 3277db6ed55dSShreyas NC case SKL_TKN_MM_U32_FMT_ID: 3278db6ed55dSShreyas NC if (!fmt) 3279db6ed55dSShreyas NC return -EINVAL; 3280db6ed55dSShreyas NC 3281db6ed55dSShreyas NC fmt->fmt_idx = tkn_elem->value; 3282db6ed55dSShreyas NC intf_val_idx = tkn_elem->value; 3283db6ed55dSShreyas NC break; 3284db6ed55dSShreyas NC 3285db6ed55dSShreyas NC case SKL_TKN_MM_U32_CPS: 3286db6ed55dSShreyas NC case SKL_TKN_MM_U32_DMA_SIZE: 3287db6ed55dSShreyas NC case SKL_TKN_MM_U32_CPC: 3288db6ed55dSShreyas NC case SKL_TKN_U32_MEM_PAGES: 3289db6ed55dSShreyas NC case SKL_TKN_U32_OBS: 3290db6ed55dSShreyas NC case SKL_TKN_U32_IBS: 3291db6ed55dSShreyas NC case SKL_TKN_MM_U32_RES_PIN_ID: 3292db6ed55dSShreyas NC case SKL_TKN_MM_U32_PIN_BUF: 3293db6ed55dSShreyas NC ret = skl_tplg_fill_res_tkn(dev, tkn_elem, res, pin_idx, dir); 3294db6ed55dSShreyas NC if (ret < 0) 3295db6ed55dSShreyas NC return ret; 3296db6ed55dSShreyas NC 3297db6ed55dSShreyas NC break; 3298db6ed55dSShreyas NC 3299db6ed55dSShreyas NC case SKL_TKN_MM_U32_NUM_IN_FMT: 3300db6ed55dSShreyas NC if (!fmt) 3301db6ed55dSShreyas NC return -EINVAL; 3302db6ed55dSShreyas NC 3303db6ed55dSShreyas NC res->nr_input_pins = tkn_elem->value; 3304db6ed55dSShreyas NC break; 3305db6ed55dSShreyas NC 3306db6ed55dSShreyas NC case SKL_TKN_MM_U32_NUM_OUT_FMT: 3307db6ed55dSShreyas NC if (!fmt) 3308db6ed55dSShreyas NC return -EINVAL; 3309db6ed55dSShreyas NC 3310db6ed55dSShreyas NC res->nr_output_pins = tkn_elem->value; 3311db6ed55dSShreyas NC break; 3312db6ed55dSShreyas NC 3313db6ed55dSShreyas NC case SKL_TKN_U32_FMT_CH: 3314db6ed55dSShreyas NC case SKL_TKN_U32_FMT_FREQ: 3315db6ed55dSShreyas NC case SKL_TKN_U32_FMT_BIT_DEPTH: 3316db6ed55dSShreyas NC case SKL_TKN_U32_FMT_SAMPLE_SIZE: 3317db6ed55dSShreyas NC case SKL_TKN_U32_FMT_CH_CONFIG: 3318db6ed55dSShreyas NC case SKL_TKN_U32_FMT_INTERLEAVE: 3319db6ed55dSShreyas NC case SKL_TKN_U32_FMT_SAMPLE_TYPE: 3320db6ed55dSShreyas NC case SKL_TKN_U32_FMT_CH_MAP: 3321db6ed55dSShreyas NC case SKL_TKN_MM_U32_INTF_PIN_ID: 3322db6ed55dSShreyas NC ret = skl_tplg_manifest_fill_fmt(dev, fmt, tkn_elem, 3323db6ed55dSShreyas NC dir, pin_idx); 3324db6ed55dSShreyas NC if (ret < 0) 3325db6ed55dSShreyas NC return ret; 3326541070ceSShreyas NC break; 3327541070ceSShreyas NC 3328541070ceSShreyas NC default: 3329ecd286a9SColin Ian King dev_err(dev, "Not a manifest token %d\n", tkn_elem->token); 3330541070ceSShreyas NC return -EINVAL; 3331541070ceSShreyas NC } 3332db6ed55dSShreyas NC tkn_count++; 3333541070ceSShreyas NC 3334541070ceSShreyas NC return tkn_count; 3335541070ceSShreyas NC } 3336541070ceSShreyas NC 3337541070ceSShreyas NC /* 3338541070ceSShreyas NC * Fill the manifest structure by parsing the tokens based on the 3339541070ceSShreyas NC * type. 3340541070ceSShreyas NC */ 3341541070ceSShreyas NC static int skl_tplg_get_manifest_tkn(struct device *dev, 3342bcc2a2dcSCezary Rojewski char *pvt_data, struct skl_dev *skl, 3343541070ceSShreyas NC int block_size) 3344541070ceSShreyas NC { 3345541070ceSShreyas NC int tkn_count = 0, ret; 3346541070ceSShreyas NC int off = 0, tuple_size = 0; 3347096769eaSAmadeusz Sławiński u8 uuid_index = 0; 3348541070ceSShreyas NC struct snd_soc_tplg_vendor_array *array; 3349541070ceSShreyas NC struct snd_soc_tplg_vendor_value_elem *tkn_elem; 3350541070ceSShreyas NC 3351541070ceSShreyas NC if (block_size <= 0) 3352541070ceSShreyas NC return -EINVAL; 3353541070ceSShreyas NC 3354541070ceSShreyas NC while (tuple_size < block_size) { 3355541070ceSShreyas NC array = (struct snd_soc_tplg_vendor_array *)(pvt_data + off); 3356541070ceSShreyas NC off += array->size; 3357541070ceSShreyas NC switch (array->type) { 3358541070ceSShreyas NC case SND_SOC_TPLG_TUPLE_TYPE_STRING: 3359eee0e16fSJeeja KP ret = skl_tplg_get_str_tkn(dev, array, skl); 3360541070ceSShreyas NC 3361541070ceSShreyas NC if (ret < 0) 3362541070ceSShreyas NC return ret; 33630a716776SShreyas NC tkn_count = ret; 3364541070ceSShreyas NC 3365541070ceSShreyas NC tuple_size += tkn_count * 3366541070ceSShreyas NC sizeof(struct snd_soc_tplg_vendor_string_elem); 3367541070ceSShreyas NC continue; 3368541070ceSShreyas NC 3369541070ceSShreyas NC case SND_SOC_TPLG_TUPLE_TYPE_UUID: 3370096769eaSAmadeusz Sławiński if (array->uuid->token != SKL_TKN_UUID) { 3371096769eaSAmadeusz Sławiński dev_err(dev, "Not an UUID token: %d\n", 3372096769eaSAmadeusz Sławiński array->uuid->token); 3373096769eaSAmadeusz Sławiński return -EINVAL; 3374096769eaSAmadeusz Sławiński } 3375096769eaSAmadeusz Sławiński if (uuid_index >= skl->nr_modules) { 3376096769eaSAmadeusz Sławiński dev_err(dev, "Too many UUID tokens\n"); 3377096769eaSAmadeusz Sławiński return -EINVAL; 3378096769eaSAmadeusz Sławiński } 3379cade2f59SAndy Shevchenko import_guid(&skl->modules[uuid_index++]->uuid, 3380cade2f59SAndy Shevchenko array->uuid->uuid); 3381db6ed55dSShreyas NC 3382db6ed55dSShreyas NC tuple_size += sizeof(*array->uuid); 3383541070ceSShreyas NC continue; 3384541070ceSShreyas NC 3385541070ceSShreyas NC default: 3386541070ceSShreyas NC tkn_elem = array->value; 3387541070ceSShreyas NC tkn_count = 0; 3388541070ceSShreyas NC break; 3389541070ceSShreyas NC } 3390541070ceSShreyas NC 3391541070ceSShreyas NC while (tkn_count <= array->num_elems - 1) { 3392541070ceSShreyas NC ret = skl_tplg_get_int_tkn(dev, 3393eee0e16fSJeeja KP tkn_elem, skl); 3394541070ceSShreyas NC if (ret < 0) 3395541070ceSShreyas NC return ret; 3396541070ceSShreyas NC 3397541070ceSShreyas NC tkn_count = tkn_count + ret; 3398541070ceSShreyas NC tkn_elem++; 3399541070ceSShreyas NC } 34009fc129f6SShreyas NC tuple_size += (tkn_count * sizeof(*tkn_elem)); 3401541070ceSShreyas NC tkn_count = 0; 3402541070ceSShreyas NC } 3403541070ceSShreyas NC 34049fc129f6SShreyas NC return off; 3405541070ceSShreyas NC } 3406541070ceSShreyas NC 3407541070ceSShreyas NC /* 3408541070ceSShreyas NC * Parse manifest private data for tokens. The private data block is 3409541070ceSShreyas NC * preceded by descriptors for type and size of data block. 3410541070ceSShreyas NC */ 3411541070ceSShreyas NC static int skl_tplg_get_manifest_data(struct snd_soc_tplg_manifest *manifest, 3412bcc2a2dcSCezary Rojewski struct device *dev, struct skl_dev *skl) 3413541070ceSShreyas NC { 3414541070ceSShreyas NC struct snd_soc_tplg_vendor_array *array; 3415541070ceSShreyas NC int num_blocks, block_size = 0, block_type, off = 0; 3416541070ceSShreyas NC char *data; 3417541070ceSShreyas NC int ret; 3418541070ceSShreyas NC 3419541070ceSShreyas NC /* Read the NUM_DATA_BLOCKS descriptor */ 3420541070ceSShreyas NC array = (struct snd_soc_tplg_vendor_array *)manifest->priv.data; 3421541070ceSShreyas NC ret = skl_tplg_get_desc_blocks(dev, array); 3422541070ceSShreyas NC if (ret < 0) 3423541070ceSShreyas NC return ret; 3424541070ceSShreyas NC num_blocks = ret; 3425541070ceSShreyas NC 3426541070ceSShreyas NC off += array->size; 3427541070ceSShreyas NC /* Read the BLOCK_TYPE and BLOCK_SIZE descriptor */ 3428541070ceSShreyas NC while (num_blocks > 0) { 34299fc129f6SShreyas NC array = (struct snd_soc_tplg_vendor_array *) 34309fc129f6SShreyas NC (manifest->priv.data + off); 3431541070ceSShreyas NC ret = skl_tplg_get_desc_blocks(dev, array); 3432541070ceSShreyas NC 3433541070ceSShreyas NC if (ret < 0) 3434541070ceSShreyas NC return ret; 3435541070ceSShreyas NC block_type = ret; 3436541070ceSShreyas NC off += array->size; 3437541070ceSShreyas NC 3438541070ceSShreyas NC array = (struct snd_soc_tplg_vendor_array *) 3439541070ceSShreyas NC (manifest->priv.data + off); 3440541070ceSShreyas NC 3441541070ceSShreyas NC ret = skl_tplg_get_desc_blocks(dev, array); 3442541070ceSShreyas NC 3443541070ceSShreyas NC if (ret < 0) 3444541070ceSShreyas NC return ret; 3445541070ceSShreyas NC block_size = ret; 3446541070ceSShreyas NC off += array->size; 3447541070ceSShreyas NC 3448541070ceSShreyas NC array = (struct snd_soc_tplg_vendor_array *) 3449541070ceSShreyas NC (manifest->priv.data + off); 3450541070ceSShreyas NC 3451541070ceSShreyas NC data = (manifest->priv.data + off); 3452541070ceSShreyas NC 3453541070ceSShreyas NC if (block_type == SKL_TYPE_TUPLE) { 3454eee0e16fSJeeja KP ret = skl_tplg_get_manifest_tkn(dev, data, skl, 3455541070ceSShreyas NC block_size); 3456541070ceSShreyas NC 3457541070ceSShreyas NC if (ret < 0) 3458541070ceSShreyas NC return ret; 3459541070ceSShreyas NC 3460541070ceSShreyas NC --num_blocks; 3461541070ceSShreyas NC } else { 3462541070ceSShreyas NC return -EINVAL; 3463541070ceSShreyas NC } 34649fc129f6SShreyas NC off += ret; 3465541070ceSShreyas NC } 3466541070ceSShreyas NC 3467541070ceSShreyas NC return 0; 3468541070ceSShreyas NC } 3469541070ceSShreyas NC 3470c60b613aSLiam Girdwood static int skl_manifest_load(struct snd_soc_component *cmpnt, int index, 347115ecaba9SKranthi G struct snd_soc_tplg_manifest *manifest) 347215ecaba9SKranthi G { 347376f56faeSRakesh Ughreja struct hdac_bus *bus = snd_soc_component_get_drvdata(cmpnt); 3474bcc2a2dcSCezary Rojewski struct skl_dev *skl = bus_to_skl(bus); 347515ecaba9SKranthi G 3476c15ad605SVinod Koul /* proceed only if we have private data defined */ 3477c15ad605SVinod Koul if (manifest->priv.size == 0) 3478c15ad605SVinod Koul return 0; 3479c15ad605SVinod Koul 3480eee0e16fSJeeja KP skl_tplg_get_manifest_data(manifest, bus->dev, skl); 3481541070ceSShreyas NC 3482bcc2a2dcSCezary Rojewski if (skl->lib_count > SKL_MAX_LIB) { 348315ecaba9SKranthi G dev_err(bus->dev, "Exceeding max Library count. Got:%d\n", 3484bcc2a2dcSCezary Rojewski skl->lib_count); 3485eee0e16fSJeeja KP return -EINVAL; 348615ecaba9SKranthi G } 348715ecaba9SKranthi G 3488eee0e16fSJeeja KP return 0; 348915ecaba9SKranthi G } 349015ecaba9SKranthi G 34913af36706SVinod Koul static struct snd_soc_tplg_ops skl_tplg_ops = { 34923af36706SVinod Koul .widget_load = skl_tplg_widget_load, 3493140adfbaSJeeja KP .control_load = skl_tplg_control_load, 3494140adfbaSJeeja KP .bytes_ext_ops = skl_tlv_ops, 3495140adfbaSJeeja KP .bytes_ext_ops_count = ARRAY_SIZE(skl_tlv_ops), 34967a1b749bSDharageswari R .io_ops = skl_tplg_kcontrol_ops, 34977a1b749bSDharageswari R .io_ops_count = ARRAY_SIZE(skl_tplg_kcontrol_ops), 349815ecaba9SKranthi G .manifest = skl_manifest_load, 3499606e21fdSGuneshwor Singh .dai_load = skl_dai_load, 35003af36706SVinod Koul }; 35013af36706SVinod Koul 3502287af4f9SJeeja KP /* 3503287af4f9SJeeja KP * A pipe can have multiple modules, each of them will be a DAPM widget as 3504287af4f9SJeeja KP * well. While managing a pipeline we need to get the list of all the 3505287af4f9SJeeja KP * widgets in a pipelines, so this helper - skl_tplg_create_pipe_widget_list() 3506287af4f9SJeeja KP * helps to get the SKL type widgets in that pipeline 3507287af4f9SJeeja KP */ 350856b03b4cSKuninori Morimoto static int skl_tplg_create_pipe_widget_list(struct snd_soc_component *component) 3509287af4f9SJeeja KP { 3510287af4f9SJeeja KP struct snd_soc_dapm_widget *w; 3511287af4f9SJeeja KP struct skl_module_cfg *mcfg = NULL; 3512287af4f9SJeeja KP struct skl_pipe_module *p_module = NULL; 3513287af4f9SJeeja KP struct skl_pipe *pipe; 3514287af4f9SJeeja KP 351556b03b4cSKuninori Morimoto list_for_each_entry(w, &component->card->widgets, list) { 3516a1f362d8SMark Brown if (is_skl_dsp_widget_type(w, component->dev) && w->priv) { 3517287af4f9SJeeja KP mcfg = w->priv; 3518287af4f9SJeeja KP pipe = mcfg->pipe; 3519287af4f9SJeeja KP 352056b03b4cSKuninori Morimoto p_module = devm_kzalloc(component->dev, 3521287af4f9SJeeja KP sizeof(*p_module), GFP_KERNEL); 3522287af4f9SJeeja KP if (!p_module) 3523287af4f9SJeeja KP return -ENOMEM; 3524287af4f9SJeeja KP 3525287af4f9SJeeja KP p_module->w = w; 3526287af4f9SJeeja KP list_add_tail(&p_module->node, &pipe->w_list); 3527287af4f9SJeeja KP } 3528287af4f9SJeeja KP } 3529287af4f9SJeeja KP 3530287af4f9SJeeja KP return 0; 3531287af4f9SJeeja KP } 3532287af4f9SJeeja KP 3533bcc2a2dcSCezary Rojewski static void skl_tplg_set_pipe_type(struct skl_dev *skl, struct skl_pipe *pipe) 3534f0aa94faSJeeja KP { 3535f0aa94faSJeeja KP struct skl_pipe_module *w_module; 3536f0aa94faSJeeja KP struct snd_soc_dapm_widget *w; 3537f0aa94faSJeeja KP struct skl_module_cfg *mconfig; 3538f0aa94faSJeeja KP bool host_found = false, link_found = false; 3539f0aa94faSJeeja KP 3540f0aa94faSJeeja KP list_for_each_entry(w_module, &pipe->w_list, node) { 3541f0aa94faSJeeja KP w = w_module->w; 3542f0aa94faSJeeja KP mconfig = w->priv; 3543f0aa94faSJeeja KP 3544f0aa94faSJeeja KP if (mconfig->dev_type == SKL_DEVICE_HDAHOST) 3545f0aa94faSJeeja KP host_found = true; 3546f0aa94faSJeeja KP else if (mconfig->dev_type != SKL_DEVICE_NONE) 3547f0aa94faSJeeja KP link_found = true; 3548f0aa94faSJeeja KP } 3549f0aa94faSJeeja KP 3550f0aa94faSJeeja KP if (host_found && link_found) 3551f0aa94faSJeeja KP pipe->passthru = true; 3552f0aa94faSJeeja KP else 3553f0aa94faSJeeja KP pipe->passthru = false; 3554f0aa94faSJeeja KP } 3555f0aa94faSJeeja KP 35563af36706SVinod Koul /* 35573af36706SVinod Koul * SKL topology init routine 35583af36706SVinod Koul */ 355976f56faeSRakesh Ughreja int skl_tplg_init(struct snd_soc_component *component, struct hdac_bus *bus) 35603af36706SVinod Koul { 35613af36706SVinod Koul int ret; 35623af36706SVinod Koul const struct firmware *fw; 3563bcc2a2dcSCezary Rojewski struct skl_dev *skl = bus_to_skl(bus); 3564f0aa94faSJeeja KP struct skl_pipeline *ppl; 35653af36706SVinod Koul 35664b235c43SVinod Koul ret = request_firmware(&fw, skl->tplg_name, bus->dev); 35673af36706SVinod Koul if (ret < 0) { 356819de7179SChintan Patel dev_info(bus->dev, "tplg fw %s load failed with %d, falling back to dfw_sst.bin", 35694b235c43SVinod Koul skl->tplg_name, ret); 35704b235c43SVinod Koul ret = request_firmware(&fw, "dfw_sst.bin", bus->dev); 35714b235c43SVinod Koul if (ret < 0) { 35724b235c43SVinod Koul dev_err(bus->dev, "Fallback tplg fw %s load failed with %d\n", 35733af36706SVinod Koul "dfw_sst.bin", ret); 35743af36706SVinod Koul return ret; 35753af36706SVinod Koul } 35764b235c43SVinod Koul } 35773af36706SVinod Koul 35783af36706SVinod Koul /* 35793af36706SVinod Koul * The complete tplg for SKL is loaded as index 0, we don't use 35803af36706SVinod Koul * any other index 35813af36706SVinod Koul */ 35826f437917SAmadeusz Sławiński ret = snd_soc_tplg_component_load(component, &skl_tplg_ops, fw, 0); 35833af36706SVinod Koul if (ret < 0) { 35843af36706SVinod Koul dev_err(bus->dev, "tplg component load failed%d\n", ret); 35856f437917SAmadeusz Sławiński goto err; 35863af36706SVinod Koul } 35873af36706SVinod Koul 358856b03b4cSKuninori Morimoto ret = skl_tplg_create_pipe_widget_list(component); 35896f437917SAmadeusz Sławiński if (ret < 0) { 35906f437917SAmadeusz Sławiński dev_err(bus->dev, "tplg create pipe widget list failed%d\n", 35916f437917SAmadeusz Sławiński ret); 35926f437917SAmadeusz Sławiński goto err; 35936f437917SAmadeusz Sławiński } 3594d8018361SVinod Koul 3595f0aa94faSJeeja KP list_for_each_entry(ppl, &skl->ppl_list, node) 3596f0aa94faSJeeja KP skl_tplg_set_pipe_type(skl, ppl->pipe); 35973af36706SVinod Koul 35986f437917SAmadeusz Sławiński err: 35996f437917SAmadeusz Sławiński release_firmware(fw); 36006f437917SAmadeusz Sławiński return ret; 36013af36706SVinod Koul } 3602e79986ceSAmadeusz Sławiński 3603e79986ceSAmadeusz Sławiński void skl_tplg_exit(struct snd_soc_component *component, struct hdac_bus *bus) 3604e79986ceSAmadeusz Sławiński { 3605bcc2a2dcSCezary Rojewski struct skl_dev *skl = bus_to_skl(bus); 3606e79986ceSAmadeusz Sławiński struct skl_pipeline *ppl, *tmp; 3607e79986ceSAmadeusz Sławiński 3608e79986ceSAmadeusz Sławiński if (!list_empty(&skl->ppl_list)) 3609e79986ceSAmadeusz Sławiński list_for_each_entry_safe(ppl, tmp, &skl->ppl_list, node) 3610e79986ceSAmadeusz Sławiński list_del(&ppl->node); 3611e79986ceSAmadeusz Sławiński 3612e79986ceSAmadeusz Sławiński /* clean up topology */ 3613e79986ceSAmadeusz Sławiński snd_soc_tplg_component_remove(component, SND_SOC_TPLG_INDEX_ALL); 3614e79986ceSAmadeusz Sławiński } 3615