1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) 2 // 3 // This file is provided under a dual BSD/GPLv2 license. When using or 4 // redistributing this file, you may do so under either license. 5 // 6 // Copyright(c) 2021 Intel Corporation. All rights reserved. 7 // 8 // 9 10 #include <uapi/sound/sof/tokens.h> 11 #include <sound/pcm_params.h> 12 #include "sof-priv.h" 13 #include "sof-audio.h" 14 #include "ipc3-ops.h" 15 #include "ops.h" 16 17 /* Full volume for default values */ 18 #define VOL_ZERO_DB BIT(VOLUME_FWL) 19 20 struct sof_widget_data { 21 int ctrl_type; 22 int ipc_cmd; 23 struct sof_abi_hdr *pdata; 24 struct snd_sof_control *control; 25 }; 26 27 struct sof_process_types { 28 const char *name; 29 enum sof_ipc_process_type type; 30 enum sof_comp_type comp_type; 31 }; 32 33 static const struct sof_process_types sof_process[] = { 34 {"EQFIR", SOF_PROCESS_EQFIR, SOF_COMP_EQ_FIR}, 35 {"EQIIR", SOF_PROCESS_EQIIR, SOF_COMP_EQ_IIR}, 36 {"KEYWORD_DETECT", SOF_PROCESS_KEYWORD_DETECT, SOF_COMP_KEYWORD_DETECT}, 37 {"KPB", SOF_PROCESS_KPB, SOF_COMP_KPB}, 38 {"CHAN_SELECTOR", SOF_PROCESS_CHAN_SELECTOR, SOF_COMP_SELECTOR}, 39 {"MUX", SOF_PROCESS_MUX, SOF_COMP_MUX}, 40 {"DEMUX", SOF_PROCESS_DEMUX, SOF_COMP_DEMUX}, 41 {"DCBLOCK", SOF_PROCESS_DCBLOCK, SOF_COMP_DCBLOCK}, 42 {"SMART_AMP", SOF_PROCESS_SMART_AMP, SOF_COMP_SMART_AMP}, 43 }; 44 45 static enum sof_ipc_process_type find_process(const char *name) 46 { 47 int i; 48 49 for (i = 0; i < ARRAY_SIZE(sof_process); i++) { 50 if (strcmp(name, sof_process[i].name) == 0) 51 return sof_process[i].type; 52 } 53 54 return SOF_PROCESS_NONE; 55 } 56 57 static int get_token_process_type(void *elem, void *object, u32 offset) 58 { 59 u32 *val = (u32 *)((u8 *)object + offset); 60 61 *val = find_process((const char *)elem); 62 return 0; 63 } 64 65 /* Buffers */ 66 static const struct sof_topology_token buffer_tokens[] = { 67 {SOF_TKN_BUF_SIZE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 68 offsetof(struct sof_ipc_buffer, size)}, 69 {SOF_TKN_BUF_CAPS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 70 offsetof(struct sof_ipc_buffer, caps)}, 71 }; 72 73 /* DAI */ 74 static const struct sof_topology_token dai_tokens[] = { 75 {SOF_TKN_DAI_TYPE, SND_SOC_TPLG_TUPLE_TYPE_STRING, get_token_dai_type, 76 offsetof(struct sof_ipc_comp_dai, type)}, 77 {SOF_TKN_DAI_INDEX, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 78 offsetof(struct sof_ipc_comp_dai, dai_index)}, 79 {SOF_TKN_DAI_DIRECTION, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 80 offsetof(struct sof_ipc_comp_dai, direction)}, 81 }; 82 83 /* BE DAI link */ 84 static const struct sof_topology_token dai_link_tokens[] = { 85 {SOF_TKN_DAI_TYPE, SND_SOC_TPLG_TUPLE_TYPE_STRING, get_token_dai_type, 86 offsetof(struct sof_ipc_dai_config, type)}, 87 {SOF_TKN_DAI_INDEX, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 88 offsetof(struct sof_ipc_dai_config, dai_index)}, 89 }; 90 91 /* scheduling */ 92 static const struct sof_topology_token sched_tokens[] = { 93 {SOF_TKN_SCHED_PERIOD, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 94 offsetof(struct sof_ipc_pipe_new, period)}, 95 {SOF_TKN_SCHED_PRIORITY, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 96 offsetof(struct sof_ipc_pipe_new, priority)}, 97 {SOF_TKN_SCHED_MIPS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 98 offsetof(struct sof_ipc_pipe_new, period_mips)}, 99 {SOF_TKN_SCHED_CORE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 100 offsetof(struct sof_ipc_pipe_new, core)}, 101 {SOF_TKN_SCHED_FRAMES, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 102 offsetof(struct sof_ipc_pipe_new, frames_per_sched)}, 103 {SOF_TKN_SCHED_TIME_DOMAIN, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 104 offsetof(struct sof_ipc_pipe_new, time_domain)}, 105 }; 106 107 static const struct sof_topology_token pipeline_tokens[] = { 108 {SOF_TKN_SCHED_DYNAMIC_PIPELINE, SND_SOC_TPLG_TUPLE_TYPE_BOOL, get_token_u16, 109 offsetof(struct snd_sof_widget, dynamic_pipeline_widget)}, 110 111 }; 112 113 /* volume */ 114 static const struct sof_topology_token volume_tokens[] = { 115 {SOF_TKN_VOLUME_RAMP_STEP_TYPE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 116 offsetof(struct sof_ipc_comp_volume, ramp)}, 117 {SOF_TKN_VOLUME_RAMP_STEP_MS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 118 offsetof(struct sof_ipc_comp_volume, initial_ramp)}, 119 }; 120 121 /* SRC */ 122 static const struct sof_topology_token src_tokens[] = { 123 {SOF_TKN_SRC_RATE_IN, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 124 offsetof(struct sof_ipc_comp_src, source_rate)}, 125 {SOF_TKN_SRC_RATE_OUT, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 126 offsetof(struct sof_ipc_comp_src, sink_rate)}, 127 }; 128 129 /* ASRC */ 130 static const struct sof_topology_token asrc_tokens[] = { 131 {SOF_TKN_ASRC_RATE_IN, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 132 offsetof(struct sof_ipc_comp_asrc, source_rate)}, 133 {SOF_TKN_ASRC_RATE_OUT, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 134 offsetof(struct sof_ipc_comp_asrc, sink_rate)}, 135 {SOF_TKN_ASRC_ASYNCHRONOUS_MODE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 136 offsetof(struct sof_ipc_comp_asrc, asynchronous_mode)}, 137 {SOF_TKN_ASRC_OPERATION_MODE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 138 offsetof(struct sof_ipc_comp_asrc, operation_mode)}, 139 }; 140 141 /* EFFECT */ 142 static const struct sof_topology_token process_tokens[] = { 143 {SOF_TKN_PROCESS_TYPE, SND_SOC_TPLG_TUPLE_TYPE_STRING, get_token_process_type, 144 offsetof(struct sof_ipc_comp_process, type)}, 145 }; 146 147 /* PCM */ 148 static const struct sof_topology_token pcm_tokens[] = { 149 {SOF_TKN_PCM_DMAC_CONFIG, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 150 offsetof(struct sof_ipc_comp_host, dmac_config)}, 151 }; 152 153 /* Generic components */ 154 static const struct sof_topology_token comp_tokens[] = { 155 {SOF_TKN_COMP_PERIOD_SINK_COUNT, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 156 offsetof(struct sof_ipc_comp_config, periods_sink)}, 157 {SOF_TKN_COMP_PERIOD_SOURCE_COUNT, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 158 offsetof(struct sof_ipc_comp_config, periods_source)}, 159 {SOF_TKN_COMP_FORMAT, 160 SND_SOC_TPLG_TUPLE_TYPE_STRING, get_token_comp_format, 161 offsetof(struct sof_ipc_comp_config, frame_fmt)}, 162 }; 163 164 /* SSP */ 165 static const struct sof_topology_token ssp_tokens[] = { 166 {SOF_TKN_INTEL_SSP_CLKS_CONTROL, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 167 offsetof(struct sof_ipc_dai_ssp_params, clks_control)}, 168 {SOF_TKN_INTEL_SSP_MCLK_ID, SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, 169 offsetof(struct sof_ipc_dai_ssp_params, mclk_id)}, 170 {SOF_TKN_INTEL_SSP_SAMPLE_BITS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 171 offsetof(struct sof_ipc_dai_ssp_params, sample_valid_bits)}, 172 {SOF_TKN_INTEL_SSP_FRAME_PULSE_WIDTH, SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, 173 offsetof(struct sof_ipc_dai_ssp_params, frame_pulse_width)}, 174 {SOF_TKN_INTEL_SSP_QUIRKS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 175 offsetof(struct sof_ipc_dai_ssp_params, quirks)}, 176 {SOF_TKN_INTEL_SSP_TDM_PADDING_PER_SLOT, SND_SOC_TPLG_TUPLE_TYPE_BOOL, get_token_u16, 177 offsetof(struct sof_ipc_dai_ssp_params, tdm_per_slot_padding_flag)}, 178 {SOF_TKN_INTEL_SSP_BCLK_DELAY, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 179 offsetof(struct sof_ipc_dai_ssp_params, bclk_delay)}, 180 }; 181 182 /* ALH */ 183 static const struct sof_topology_token alh_tokens[] = { 184 {SOF_TKN_INTEL_ALH_RATE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 185 offsetof(struct sof_ipc_dai_alh_params, rate)}, 186 {SOF_TKN_INTEL_ALH_CH, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 187 offsetof(struct sof_ipc_dai_alh_params, channels)}, 188 }; 189 190 /* DMIC */ 191 static const struct sof_topology_token dmic_tokens[] = { 192 {SOF_TKN_INTEL_DMIC_DRIVER_VERSION, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 193 offsetof(struct sof_ipc_dai_dmic_params, driver_ipc_version)}, 194 {SOF_TKN_INTEL_DMIC_CLK_MIN, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 195 offsetof(struct sof_ipc_dai_dmic_params, pdmclk_min)}, 196 {SOF_TKN_INTEL_DMIC_CLK_MAX, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 197 offsetof(struct sof_ipc_dai_dmic_params, pdmclk_max)}, 198 {SOF_TKN_INTEL_DMIC_SAMPLE_RATE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 199 offsetof(struct sof_ipc_dai_dmic_params, fifo_fs)}, 200 {SOF_TKN_INTEL_DMIC_DUTY_MIN, SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, 201 offsetof(struct sof_ipc_dai_dmic_params, duty_min)}, 202 {SOF_TKN_INTEL_DMIC_DUTY_MAX, SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, 203 offsetof(struct sof_ipc_dai_dmic_params, duty_max)}, 204 {SOF_TKN_INTEL_DMIC_NUM_PDM_ACTIVE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 205 offsetof(struct sof_ipc_dai_dmic_params, num_pdm_active)}, 206 {SOF_TKN_INTEL_DMIC_FIFO_WORD_LENGTH, SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, 207 offsetof(struct sof_ipc_dai_dmic_params, fifo_bits)}, 208 {SOF_TKN_INTEL_DMIC_UNMUTE_RAMP_TIME_MS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 209 offsetof(struct sof_ipc_dai_dmic_params, unmute_ramp_time)}, 210 }; 211 212 /* ESAI */ 213 static const struct sof_topology_token esai_tokens[] = { 214 {SOF_TKN_IMX_ESAI_MCLK_ID, SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, 215 offsetof(struct sof_ipc_dai_esai_params, mclk_id)}, 216 }; 217 218 /* SAI */ 219 static const struct sof_topology_token sai_tokens[] = { 220 {SOF_TKN_IMX_SAI_MCLK_ID, SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, 221 offsetof(struct sof_ipc_dai_sai_params, mclk_id)}, 222 }; 223 224 /* 225 * DMIC PDM Tokens 226 * SOF_TKN_INTEL_DMIC_PDM_CTRL_ID should be the first token 227 * as it increments the index while parsing the array of pdm tokens 228 * and determines the correct offset 229 */ 230 static const struct sof_topology_token dmic_pdm_tokens[] = { 231 {SOF_TKN_INTEL_DMIC_PDM_CTRL_ID, SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, 232 offsetof(struct sof_ipc_dai_dmic_pdm_ctrl, id)}, 233 {SOF_TKN_INTEL_DMIC_PDM_MIC_A_Enable, SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, 234 offsetof(struct sof_ipc_dai_dmic_pdm_ctrl, enable_mic_a)}, 235 {SOF_TKN_INTEL_DMIC_PDM_MIC_B_Enable, SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, 236 offsetof(struct sof_ipc_dai_dmic_pdm_ctrl, enable_mic_b)}, 237 {SOF_TKN_INTEL_DMIC_PDM_POLARITY_A, SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, 238 offsetof(struct sof_ipc_dai_dmic_pdm_ctrl, polarity_mic_a)}, 239 {SOF_TKN_INTEL_DMIC_PDM_POLARITY_B, SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, 240 offsetof(struct sof_ipc_dai_dmic_pdm_ctrl, polarity_mic_b)}, 241 {SOF_TKN_INTEL_DMIC_PDM_CLK_EDGE, SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, 242 offsetof(struct sof_ipc_dai_dmic_pdm_ctrl, clk_edge)}, 243 {SOF_TKN_INTEL_DMIC_PDM_SKEW, SND_SOC_TPLG_TUPLE_TYPE_SHORT, get_token_u16, 244 offsetof(struct sof_ipc_dai_dmic_pdm_ctrl, skew)}, 245 }; 246 247 /* HDA */ 248 static const struct sof_topology_token hda_tokens[] = { 249 {SOF_TKN_INTEL_HDA_RATE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 250 offsetof(struct sof_ipc_dai_hda_params, rate)}, 251 {SOF_TKN_INTEL_HDA_CH, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 252 offsetof(struct sof_ipc_dai_hda_params, channels)}, 253 }; 254 255 /* AFE */ 256 static const struct sof_topology_token afe_tokens[] = { 257 {SOF_TKN_MEDIATEK_AFE_RATE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 258 offsetof(struct sof_ipc_dai_mtk_afe_params, rate)}, 259 {SOF_TKN_MEDIATEK_AFE_CH, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 260 offsetof(struct sof_ipc_dai_mtk_afe_params, channels)}, 261 {SOF_TKN_MEDIATEK_AFE_FORMAT, SND_SOC_TPLG_TUPLE_TYPE_STRING, get_token_comp_format, 262 offsetof(struct sof_ipc_dai_mtk_afe_params, format)}, 263 }; 264 265 /* Core tokens */ 266 static const struct sof_topology_token core_tokens[] = { 267 {SOF_TKN_COMP_CORE_ID, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 268 offsetof(struct sof_ipc_comp, core)}, 269 }; 270 271 /* Component extended tokens */ 272 static const struct sof_topology_token comp_ext_tokens[] = { 273 {SOF_TKN_COMP_UUID, SND_SOC_TPLG_TUPLE_TYPE_UUID, get_token_uuid, 274 offsetof(struct snd_sof_widget, uuid)}, 275 }; 276 277 static const struct sof_token_info ipc3_token_list[SOF_TOKEN_COUNT] = { 278 [SOF_PCM_TOKENS] = {"PCM tokens", pcm_tokens, ARRAY_SIZE(pcm_tokens)}, 279 [SOF_PIPELINE_TOKENS] = {"Pipeline tokens", pipeline_tokens, ARRAY_SIZE(pipeline_tokens)}, 280 [SOF_SCHED_TOKENS] = {"Scheduler tokens", sched_tokens, ARRAY_SIZE(sched_tokens)}, 281 [SOF_COMP_TOKENS] = {"Comp tokens", comp_tokens, ARRAY_SIZE(comp_tokens)}, 282 [SOF_CORE_TOKENS] = {"Core tokens", core_tokens, ARRAY_SIZE(core_tokens)}, 283 [SOF_COMP_EXT_TOKENS] = {"AFE tokens", comp_ext_tokens, ARRAY_SIZE(comp_ext_tokens)}, 284 [SOF_BUFFER_TOKENS] = {"Buffer tokens", buffer_tokens, ARRAY_SIZE(buffer_tokens)}, 285 [SOF_VOLUME_TOKENS] = {"Volume tokens", volume_tokens, ARRAY_SIZE(volume_tokens)}, 286 [SOF_SRC_TOKENS] = {"SRC tokens", src_tokens, ARRAY_SIZE(src_tokens)}, 287 [SOF_ASRC_TOKENS] = {"ASRC tokens", asrc_tokens, ARRAY_SIZE(asrc_tokens)}, 288 [SOF_PROCESS_TOKENS] = {"Process tokens", process_tokens, ARRAY_SIZE(process_tokens)}, 289 [SOF_DAI_TOKENS] = {"DAI tokens", dai_tokens, ARRAY_SIZE(dai_tokens)}, 290 [SOF_DAI_LINK_TOKENS] = {"DAI link tokens", dai_link_tokens, ARRAY_SIZE(dai_link_tokens)}, 291 [SOF_HDA_TOKENS] = {"HDA tokens", hda_tokens, ARRAY_SIZE(hda_tokens)}, 292 [SOF_SSP_TOKENS] = {"SSP tokens", ssp_tokens, ARRAY_SIZE(ssp_tokens)}, 293 [SOF_ALH_TOKENS] = {"ALH tokens", alh_tokens, ARRAY_SIZE(alh_tokens)}, 294 [SOF_DMIC_TOKENS] = {"DMIC tokens", dmic_tokens, ARRAY_SIZE(dmic_tokens)}, 295 [SOF_DMIC_PDM_TOKENS] = {"DMIC PDM tokens", dmic_pdm_tokens, ARRAY_SIZE(dmic_pdm_tokens)}, 296 [SOF_ESAI_TOKENS] = {"ESAI tokens", esai_tokens, ARRAY_SIZE(esai_tokens)}, 297 [SOF_SAI_TOKENS] = {"SAI tokens", sai_tokens, ARRAY_SIZE(sai_tokens)}, 298 [SOF_AFE_TOKENS] = {"AFE tokens", afe_tokens, ARRAY_SIZE(afe_tokens)}, 299 }; 300 301 /** 302 * sof_comp_alloc - allocate and initialize buffer for a new component 303 * @swidget: pointer to struct snd_sof_widget containing extended data 304 * @ipc_size: IPC payload size that will be updated depending on valid 305 * extended data. 306 * @index: ID of the pipeline the component belongs to 307 * 308 * Return: The pointer to the new allocated component, NULL if failed. 309 */ 310 static void *sof_comp_alloc(struct snd_sof_widget *swidget, size_t *ipc_size, 311 int index) 312 { 313 struct sof_ipc_comp *comp; 314 size_t total_size = *ipc_size; 315 size_t ext_size = sizeof(swidget->uuid); 316 317 /* only non-zero UUID is valid */ 318 if (!guid_is_null(&swidget->uuid)) 319 total_size += ext_size; 320 321 comp = kzalloc(total_size, GFP_KERNEL); 322 if (!comp) 323 return NULL; 324 325 /* configure comp new IPC message */ 326 comp->hdr.size = total_size; 327 comp->hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_NEW; 328 comp->id = swidget->comp_id; 329 comp->pipeline_id = index; 330 comp->core = swidget->core; 331 332 /* handle the extended data if needed */ 333 if (total_size > *ipc_size) { 334 /* append extended data to the end of the component */ 335 memcpy((u8 *)comp + *ipc_size, &swidget->uuid, ext_size); 336 comp->ext_data_length = ext_size; 337 } 338 339 /* update ipc_size and return */ 340 *ipc_size = total_size; 341 return comp; 342 } 343 344 static void sof_dbg_comp_config(struct snd_soc_component *scomp, struct sof_ipc_comp_config *config) 345 { 346 dev_dbg(scomp->dev, " config: periods snk %d src %d fmt %d\n", 347 config->periods_sink, config->periods_source, 348 config->frame_fmt); 349 } 350 351 static int sof_ipc3_widget_setup_comp_host(struct snd_sof_widget *swidget) 352 { 353 struct snd_soc_component *scomp = swidget->scomp; 354 struct sof_ipc_comp_host *host; 355 size_t ipc_size = sizeof(*host); 356 int ret; 357 358 host = sof_comp_alloc(swidget, &ipc_size, swidget->pipeline_id); 359 if (!host) 360 return -ENOMEM; 361 swidget->private = host; 362 363 /* configure host comp IPC message */ 364 host->comp.type = SOF_COMP_HOST; 365 host->config.hdr.size = sizeof(host->config); 366 367 if (swidget->id == snd_soc_dapm_aif_out) 368 host->direction = SOF_IPC_STREAM_CAPTURE; 369 else 370 host->direction = SOF_IPC_STREAM_PLAYBACK; 371 372 /* parse one set of pcm_tokens */ 373 ret = sof_update_ipc_object(scomp, host, SOF_PCM_TOKENS, swidget->tuples, 374 swidget->num_tuples, sizeof(*host), 1); 375 if (ret < 0) 376 goto err; 377 378 /* parse one set of comp_tokens */ 379 ret = sof_update_ipc_object(scomp, &host->config, SOF_COMP_TOKENS, swidget->tuples, 380 swidget->num_tuples, sizeof(host->config), 1); 381 if (ret < 0) 382 goto err; 383 384 dev_dbg(scomp->dev, "loaded host %s\n", swidget->widget->name); 385 sof_dbg_comp_config(scomp, &host->config); 386 387 return 0; 388 err: 389 kfree(swidget->private); 390 swidget->private = NULL; 391 392 return ret; 393 } 394 395 static void sof_ipc3_widget_free_comp(struct snd_sof_widget *swidget) 396 { 397 kfree(swidget->private); 398 } 399 400 static int sof_ipc3_widget_setup_comp_tone(struct snd_sof_widget *swidget) 401 { 402 struct snd_soc_component *scomp = swidget->scomp; 403 struct sof_ipc_comp_tone *tone; 404 size_t ipc_size = sizeof(*tone); 405 int ret; 406 407 tone = sof_comp_alloc(swidget, &ipc_size, swidget->pipeline_id); 408 if (!tone) 409 return -ENOMEM; 410 411 swidget->private = tone; 412 413 /* configure siggen IPC message */ 414 tone->comp.type = SOF_COMP_TONE; 415 tone->config.hdr.size = sizeof(tone->config); 416 417 /* parse one set of comp tokens */ 418 ret = sof_update_ipc_object(scomp, &tone->config, SOF_COMP_TOKENS, swidget->tuples, 419 swidget->num_tuples, sizeof(tone->config), 1); 420 if (ret < 0) { 421 kfree(swidget->private); 422 swidget->private = NULL; 423 return ret; 424 } 425 426 dev_dbg(scomp->dev, "tone %s: frequency %d amplitude %d\n", 427 swidget->widget->name, tone->frequency, tone->amplitude); 428 sof_dbg_comp_config(scomp, &tone->config); 429 430 return 0; 431 } 432 433 static int sof_ipc3_widget_setup_comp_mixer(struct snd_sof_widget *swidget) 434 { 435 struct snd_soc_component *scomp = swidget->scomp; 436 struct sof_ipc_comp_mixer *mixer; 437 size_t ipc_size = sizeof(*mixer); 438 int ret; 439 440 mixer = sof_comp_alloc(swidget, &ipc_size, swidget->pipeline_id); 441 if (!mixer) 442 return -ENOMEM; 443 444 swidget->private = mixer; 445 446 /* configure mixer IPC message */ 447 mixer->comp.type = SOF_COMP_MIXER; 448 mixer->config.hdr.size = sizeof(mixer->config); 449 450 /* parse one set of comp tokens */ 451 ret = sof_update_ipc_object(scomp, &mixer->config, SOF_COMP_TOKENS, 452 swidget->tuples, swidget->num_tuples, 453 sizeof(mixer->config), 1); 454 if (ret < 0) { 455 kfree(swidget->private); 456 swidget->private = NULL; 457 458 return ret; 459 } 460 461 dev_dbg(scomp->dev, "loaded mixer %s\n", swidget->widget->name); 462 sof_dbg_comp_config(scomp, &mixer->config); 463 464 return 0; 465 } 466 467 static int sof_ipc3_widget_setup_comp_pipeline(struct snd_sof_widget *swidget) 468 { 469 struct snd_soc_component *scomp = swidget->scomp; 470 struct sof_ipc_pipe_new *pipeline; 471 struct snd_sof_widget *comp_swidget; 472 int ret; 473 474 pipeline = kzalloc(sizeof(*pipeline), GFP_KERNEL); 475 if (!pipeline) 476 return -ENOMEM; 477 478 /* configure pipeline IPC message */ 479 pipeline->hdr.size = sizeof(*pipeline); 480 pipeline->hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_PIPE_NEW; 481 pipeline->pipeline_id = swidget->pipeline_id; 482 pipeline->comp_id = swidget->comp_id; 483 484 swidget->private = pipeline; 485 486 /* component at start of pipeline is our stream id */ 487 comp_swidget = snd_sof_find_swidget(scomp, swidget->widget->sname); 488 if (!comp_swidget) { 489 dev_err(scomp->dev, "scheduler %s refers to non existent widget %s\n", 490 swidget->widget->name, swidget->widget->sname); 491 ret = -EINVAL; 492 goto err; 493 } 494 495 pipeline->sched_id = comp_swidget->comp_id; 496 497 /* parse one set of scheduler tokens */ 498 ret = sof_update_ipc_object(scomp, pipeline, SOF_SCHED_TOKENS, swidget->tuples, 499 swidget->num_tuples, sizeof(*pipeline), 1); 500 if (ret < 0) 501 goto err; 502 503 /* parse one set of pipeline tokens */ 504 ret = sof_update_ipc_object(scomp, swidget, SOF_PIPELINE_TOKENS, swidget->tuples, 505 swidget->num_tuples, sizeof(*swidget), 1); 506 if (ret < 0) 507 goto err; 508 509 if (sof_debug_check_flag(SOF_DBG_DISABLE_MULTICORE)) 510 pipeline->core = SOF_DSP_PRIMARY_CORE; 511 512 if (sof_debug_check_flag(SOF_DBG_DYNAMIC_PIPELINES_OVERRIDE)) 513 swidget->dynamic_pipeline_widget = 514 sof_debug_check_flag(SOF_DBG_DYNAMIC_PIPELINES_ENABLE); 515 516 dev_dbg(scomp->dev, "pipeline %s: period %d pri %d mips %d core %d frames %d dynamic %d\n", 517 swidget->widget->name, pipeline->period, pipeline->priority, 518 pipeline->period_mips, pipeline->core, pipeline->frames_per_sched, 519 swidget->dynamic_pipeline_widget); 520 521 swidget->core = pipeline->core; 522 523 return 0; 524 525 err: 526 kfree(swidget->private); 527 swidget->private = NULL; 528 529 return ret; 530 } 531 532 static int sof_ipc3_widget_setup_comp_buffer(struct snd_sof_widget *swidget) 533 { 534 struct snd_soc_component *scomp = swidget->scomp; 535 struct sof_ipc_buffer *buffer; 536 int ret; 537 538 buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); 539 if (!buffer) 540 return -ENOMEM; 541 542 swidget->private = buffer; 543 544 /* configure dai IPC message */ 545 buffer->comp.hdr.size = sizeof(*buffer); 546 buffer->comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_BUFFER_NEW; 547 buffer->comp.id = swidget->comp_id; 548 buffer->comp.type = SOF_COMP_BUFFER; 549 buffer->comp.pipeline_id = swidget->pipeline_id; 550 buffer->comp.core = swidget->core; 551 552 /* parse one set of buffer tokens */ 553 ret = sof_update_ipc_object(scomp, buffer, SOF_BUFFER_TOKENS, swidget->tuples, 554 swidget->num_tuples, sizeof(*buffer), 1); 555 if (ret < 0) { 556 kfree(swidget->private); 557 swidget->private = NULL; 558 return ret; 559 } 560 561 dev_dbg(scomp->dev, "buffer %s: size %d caps 0x%x\n", 562 swidget->widget->name, buffer->size, buffer->caps); 563 564 return 0; 565 } 566 567 static int sof_ipc3_widget_setup_comp_src(struct snd_sof_widget *swidget) 568 { 569 struct snd_soc_component *scomp = swidget->scomp; 570 struct sof_ipc_comp_src *src; 571 size_t ipc_size = sizeof(*src); 572 int ret; 573 574 src = sof_comp_alloc(swidget, &ipc_size, swidget->pipeline_id); 575 if (!src) 576 return -ENOMEM; 577 578 swidget->private = src; 579 580 /* configure src IPC message */ 581 src->comp.type = SOF_COMP_SRC; 582 src->config.hdr.size = sizeof(src->config); 583 584 /* parse one set of src tokens */ 585 ret = sof_update_ipc_object(scomp, src, SOF_SRC_TOKENS, swidget->tuples, 586 swidget->num_tuples, sizeof(*src), 1); 587 if (ret < 0) 588 goto err; 589 590 /* parse one set of comp tokens */ 591 ret = sof_update_ipc_object(scomp, &src->config, SOF_COMP_TOKENS, 592 swidget->tuples, swidget->num_tuples, sizeof(src->config), 1); 593 if (ret < 0) 594 goto err; 595 596 dev_dbg(scomp->dev, "src %s: source rate %d sink rate %d\n", 597 swidget->widget->name, src->source_rate, src->sink_rate); 598 sof_dbg_comp_config(scomp, &src->config); 599 600 return 0; 601 err: 602 kfree(swidget->private); 603 swidget->private = NULL; 604 605 return ret; 606 } 607 608 static int sof_ipc3_widget_setup_comp_asrc(struct snd_sof_widget *swidget) 609 { 610 struct snd_soc_component *scomp = swidget->scomp; 611 struct sof_ipc_comp_asrc *asrc; 612 size_t ipc_size = sizeof(*asrc); 613 int ret; 614 615 asrc = sof_comp_alloc(swidget, &ipc_size, swidget->pipeline_id); 616 if (!asrc) 617 return -ENOMEM; 618 619 swidget->private = asrc; 620 621 /* configure ASRC IPC message */ 622 asrc->comp.type = SOF_COMP_ASRC; 623 asrc->config.hdr.size = sizeof(asrc->config); 624 625 /* parse one set of asrc tokens */ 626 ret = sof_update_ipc_object(scomp, asrc, SOF_ASRC_TOKENS, swidget->tuples, 627 swidget->num_tuples, sizeof(*asrc), 1); 628 if (ret < 0) 629 goto err; 630 631 /* parse one set of comp tokens */ 632 ret = sof_update_ipc_object(scomp, &asrc->config, SOF_COMP_TOKENS, 633 swidget->tuples, swidget->num_tuples, sizeof(asrc->config), 1); 634 if (ret < 0) 635 goto err; 636 637 dev_dbg(scomp->dev, "asrc %s: source rate %d sink rate %d asynch %d operation %d\n", 638 swidget->widget->name, asrc->source_rate, asrc->sink_rate, 639 asrc->asynchronous_mode, asrc->operation_mode); 640 641 sof_dbg_comp_config(scomp, &asrc->config); 642 643 return 0; 644 err: 645 kfree(swidget->private); 646 swidget->private = NULL; 647 648 return ret; 649 } 650 651 /* 652 * Mux topology 653 */ 654 static int sof_ipc3_widget_setup_comp_mux(struct snd_sof_widget *swidget) 655 { 656 struct snd_soc_component *scomp = swidget->scomp; 657 struct sof_ipc_comp_mux *mux; 658 size_t ipc_size = sizeof(*mux); 659 int ret; 660 661 mux = sof_comp_alloc(swidget, &ipc_size, swidget->pipeline_id); 662 if (!mux) 663 return -ENOMEM; 664 665 swidget->private = mux; 666 667 /* configure mux IPC message */ 668 mux->comp.type = SOF_COMP_MUX; 669 mux->config.hdr.size = sizeof(mux->config); 670 671 /* parse one set of comp tokens */ 672 ret = sof_update_ipc_object(scomp, &mux->config, SOF_COMP_TOKENS, 673 swidget->tuples, swidget->num_tuples, sizeof(mux->config), 1); 674 if (ret < 0) { 675 kfree(swidget->private); 676 swidget->private = NULL; 677 return ret; 678 } 679 680 dev_dbg(scomp->dev, "loaded mux %s\n", swidget->widget->name); 681 sof_dbg_comp_config(scomp, &mux->config); 682 683 return 0; 684 } 685 686 /* 687 * PGA Topology 688 */ 689 690 static int sof_ipc3_widget_setup_comp_pga(struct snd_sof_widget *swidget) 691 { 692 struct snd_soc_component *scomp = swidget->scomp; 693 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 694 struct sof_ipc_comp_volume *volume; 695 struct snd_sof_control *scontrol; 696 size_t ipc_size = sizeof(*volume); 697 int min_step, max_step; 698 int ret; 699 700 volume = sof_comp_alloc(swidget, &ipc_size, swidget->pipeline_id); 701 if (!volume) 702 return -ENOMEM; 703 704 swidget->private = volume; 705 706 /* configure volume IPC message */ 707 volume->comp.type = SOF_COMP_VOLUME; 708 volume->config.hdr.size = sizeof(volume->config); 709 710 /* parse one set of volume tokens */ 711 ret = sof_update_ipc_object(scomp, volume, SOF_VOLUME_TOKENS, swidget->tuples, 712 swidget->num_tuples, sizeof(*volume), 1); 713 if (ret < 0) 714 goto err; 715 716 /* parse one set of comp tokens */ 717 ret = sof_update_ipc_object(scomp, &volume->config, SOF_COMP_TOKENS, 718 swidget->tuples, swidget->num_tuples, 719 sizeof(volume->config), 1); 720 if (ret < 0) 721 goto err; 722 723 dev_dbg(scomp->dev, "loaded PGA %s\n", swidget->widget->name); 724 sof_dbg_comp_config(scomp, &volume->config); 725 726 list_for_each_entry(scontrol, &sdev->kcontrol_list, list) { 727 if (scontrol->comp_id == swidget->comp_id && 728 scontrol->volume_table) { 729 min_step = scontrol->min_volume_step; 730 max_step = scontrol->max_volume_step; 731 volume->min_value = scontrol->volume_table[min_step]; 732 volume->max_value = scontrol->volume_table[max_step]; 733 volume->channels = scontrol->num_channels; 734 break; 735 } 736 } 737 738 return 0; 739 err: 740 kfree(swidget->private); 741 swidget->private = NULL; 742 743 return ret; 744 } 745 746 static int sof_get_control_data(struct snd_soc_component *scomp, 747 struct snd_soc_dapm_widget *widget, 748 struct sof_widget_data *wdata, size_t *size) 749 { 750 const struct snd_kcontrol_new *kc; 751 struct sof_ipc_ctrl_data *cdata; 752 struct soc_mixer_control *sm; 753 struct soc_bytes_ext *sbe; 754 struct soc_enum *se; 755 int i; 756 757 *size = 0; 758 759 for (i = 0; i < widget->num_kcontrols; i++) { 760 kc = &widget->kcontrol_news[i]; 761 762 switch (widget->dobj.widget.kcontrol_type[i]) { 763 case SND_SOC_TPLG_TYPE_MIXER: 764 sm = (struct soc_mixer_control *)kc->private_value; 765 wdata[i].control = sm->dobj.private; 766 break; 767 case SND_SOC_TPLG_TYPE_BYTES: 768 sbe = (struct soc_bytes_ext *)kc->private_value; 769 wdata[i].control = sbe->dobj.private; 770 break; 771 case SND_SOC_TPLG_TYPE_ENUM: 772 se = (struct soc_enum *)kc->private_value; 773 wdata[i].control = se->dobj.private; 774 break; 775 default: 776 dev_err(scomp->dev, "Unknown kcontrol type %u in widget %s\n", 777 widget->dobj.widget.kcontrol_type[i], widget->name); 778 return -EINVAL; 779 } 780 781 if (!wdata[i].control) { 782 dev_err(scomp->dev, "No scontrol for widget %s\n", widget->name); 783 return -EINVAL; 784 } 785 786 cdata = wdata[i].control->ipc_control_data; 787 wdata[i].pdata = cdata->data; 788 if (!wdata[i].pdata) 789 return -EINVAL; 790 791 /* make sure data is valid - data can be updated at runtime */ 792 if (widget->dobj.widget.kcontrol_type[i] == SND_SOC_TPLG_TYPE_BYTES && 793 wdata[i].pdata->magic != SOF_ABI_MAGIC) 794 return -EINVAL; 795 796 *size += wdata[i].pdata->size; 797 798 /* get data type */ 799 switch (cdata->cmd) { 800 case SOF_CTRL_CMD_VOLUME: 801 case SOF_CTRL_CMD_ENUM: 802 case SOF_CTRL_CMD_SWITCH: 803 wdata[i].ipc_cmd = SOF_IPC_COMP_SET_VALUE; 804 wdata[i].ctrl_type = SOF_CTRL_TYPE_VALUE_CHAN_SET; 805 break; 806 case SOF_CTRL_CMD_BINARY: 807 wdata[i].ipc_cmd = SOF_IPC_COMP_SET_DATA; 808 wdata[i].ctrl_type = SOF_CTRL_TYPE_DATA_SET; 809 break; 810 default: 811 break; 812 } 813 } 814 815 return 0; 816 } 817 818 static int sof_process_load(struct snd_soc_component *scomp, 819 struct snd_sof_widget *swidget, int type) 820 { 821 struct snd_soc_dapm_widget *widget = swidget->widget; 822 struct sof_ipc_comp_process *process; 823 struct sof_widget_data *wdata = NULL; 824 size_t ipc_data_size = 0; 825 size_t ipc_size; 826 int offset = 0; 827 int ret; 828 int i; 829 830 /* allocate struct for widget control data sizes and types */ 831 if (widget->num_kcontrols) { 832 wdata = kcalloc(widget->num_kcontrols, sizeof(*wdata), GFP_KERNEL); 833 if (!wdata) 834 return -ENOMEM; 835 836 /* get possible component controls and get size of all pdata */ 837 ret = sof_get_control_data(scomp, widget, wdata, &ipc_data_size); 838 if (ret < 0) 839 goto out; 840 } 841 842 ipc_size = sizeof(struct sof_ipc_comp_process) + ipc_data_size; 843 844 /* we are exceeding max ipc size, config needs to be sent separately */ 845 if (ipc_size > SOF_IPC_MSG_MAX_SIZE) { 846 ipc_size -= ipc_data_size; 847 ipc_data_size = 0; 848 } 849 850 process = sof_comp_alloc(swidget, &ipc_size, swidget->pipeline_id); 851 if (!process) { 852 ret = -ENOMEM; 853 goto out; 854 } 855 856 swidget->private = process; 857 858 /* configure iir IPC message */ 859 process->comp.type = type; 860 process->config.hdr.size = sizeof(process->config); 861 862 /* parse one set of comp tokens */ 863 ret = sof_update_ipc_object(scomp, &process->config, SOF_COMP_TOKENS, 864 swidget->tuples, swidget->num_tuples, 865 sizeof(process->config), 1); 866 if (ret < 0) 867 goto err; 868 869 dev_dbg(scomp->dev, "loaded process %s\n", swidget->widget->name); 870 sof_dbg_comp_config(scomp, &process->config); 871 872 /* 873 * found private data in control, so copy it. 874 * get possible component controls - get size of all pdata, 875 * then memcpy with headers 876 */ 877 if (ipc_data_size) { 878 for (i = 0; i < widget->num_kcontrols; i++) { 879 memcpy(&process->data[offset], 880 wdata[i].pdata->data, 881 wdata[i].pdata->size); 882 offset += wdata[i].pdata->size; 883 } 884 } 885 886 process->size = ipc_data_size; 887 888 kfree(wdata); 889 890 return 0; 891 err: 892 kfree(swidget->private); 893 swidget->private = NULL; 894 out: 895 kfree(wdata); 896 return ret; 897 } 898 899 static enum sof_comp_type find_process_comp_type(enum sof_ipc_process_type type) 900 { 901 int i; 902 903 for (i = 0; i < ARRAY_SIZE(sof_process); i++) { 904 if (sof_process[i].type == type) 905 return sof_process[i].comp_type; 906 } 907 908 return SOF_COMP_NONE; 909 } 910 911 /* 912 * Processing Component Topology - can be "effect", "codec", or general 913 * "processing". 914 */ 915 916 static int sof_widget_update_ipc_comp_process(struct snd_sof_widget *swidget) 917 { 918 struct snd_soc_component *scomp = swidget->scomp; 919 struct sof_ipc_comp_process config; 920 int ret; 921 922 memset(&config, 0, sizeof(config)); 923 config.comp.core = swidget->core; 924 925 /* parse one set of process tokens */ 926 ret = sof_update_ipc_object(scomp, &config, SOF_PROCESS_TOKENS, swidget->tuples, 927 swidget->num_tuples, sizeof(config), 1); 928 if (ret < 0) 929 return ret; 930 931 /* now load process specific data and send IPC */ 932 return sof_process_load(scomp, swidget, find_process_comp_type(config.type)); 933 } 934 935 static int sof_link_hda_load(struct snd_soc_component *scomp, struct snd_sof_dai_link *slink, 936 struct sof_ipc_dai_config *config, struct snd_sof_dai *dai) 937 { 938 struct sof_dai_private_data *private = dai->private; 939 u32 size = sizeof(*config); 940 int ret; 941 942 /* init IPC */ 943 memset(&config->hda, 0, sizeof(config->hda)); 944 config->hdr.size = size; 945 946 /* parse one set of HDA tokens */ 947 ret = sof_update_ipc_object(scomp, &config->hda, SOF_HDA_TOKENS, slink->tuples, 948 slink->num_tuples, size, 1); 949 if (ret < 0) 950 return ret; 951 952 dev_dbg(scomp->dev, "HDA config rate %d channels %d\n", 953 config->hda.rate, config->hda.channels); 954 955 config->hda.link_dma_ch = DMA_CHAN_INVALID; 956 957 dai->number_configs = 1; 958 dai->current_config = 0; 959 private->dai_config = kmemdup(config, size, GFP_KERNEL); 960 if (!private->dai_config) 961 return -ENOMEM; 962 963 return 0; 964 } 965 966 static void sof_dai_set_format(struct snd_soc_tplg_hw_config *hw_config, 967 struct sof_ipc_dai_config *config) 968 { 969 /* clock directions wrt codec */ 970 config->format &= ~SOF_DAI_FMT_CLOCK_PROVIDER_MASK; 971 if (hw_config->bclk_provider == SND_SOC_TPLG_BCLK_CP) { 972 /* codec is bclk provider */ 973 if (hw_config->fsync_provider == SND_SOC_TPLG_FSYNC_CP) 974 config->format |= SOF_DAI_FMT_CBP_CFP; 975 else 976 config->format |= SOF_DAI_FMT_CBP_CFC; 977 } else { 978 /* codec is bclk consumer */ 979 if (hw_config->fsync_provider == SND_SOC_TPLG_FSYNC_CP) 980 config->format |= SOF_DAI_FMT_CBC_CFP; 981 else 982 config->format |= SOF_DAI_FMT_CBC_CFC; 983 } 984 985 /* inverted clocks ? */ 986 config->format &= ~SOF_DAI_FMT_INV_MASK; 987 if (hw_config->invert_bclk) { 988 if (hw_config->invert_fsync) 989 config->format |= SOF_DAI_FMT_IB_IF; 990 else 991 config->format |= SOF_DAI_FMT_IB_NF; 992 } else { 993 if (hw_config->invert_fsync) 994 config->format |= SOF_DAI_FMT_NB_IF; 995 else 996 config->format |= SOF_DAI_FMT_NB_NF; 997 } 998 } 999 1000 static int sof_link_sai_load(struct snd_soc_component *scomp, struct snd_sof_dai_link *slink, 1001 struct sof_ipc_dai_config *config, struct snd_sof_dai *dai) 1002 { 1003 struct snd_soc_tplg_hw_config *hw_config = slink->hw_configs; 1004 struct sof_dai_private_data *private = dai->private; 1005 u32 size = sizeof(*config); 1006 int ret; 1007 1008 /* handle master/slave and inverted clocks */ 1009 sof_dai_set_format(hw_config, config); 1010 1011 /* init IPC */ 1012 memset(&config->sai, 0, sizeof(config->sai)); 1013 config->hdr.size = size; 1014 1015 /* parse one set of SAI tokens */ 1016 ret = sof_update_ipc_object(scomp, &config->sai, SOF_SAI_TOKENS, slink->tuples, 1017 slink->num_tuples, size, 1); 1018 if (ret < 0) 1019 return ret; 1020 1021 config->sai.mclk_rate = le32_to_cpu(hw_config->mclk_rate); 1022 config->sai.bclk_rate = le32_to_cpu(hw_config->bclk_rate); 1023 config->sai.fsync_rate = le32_to_cpu(hw_config->fsync_rate); 1024 config->sai.mclk_direction = hw_config->mclk_direction; 1025 1026 config->sai.tdm_slots = le32_to_cpu(hw_config->tdm_slots); 1027 config->sai.tdm_slot_width = le32_to_cpu(hw_config->tdm_slot_width); 1028 config->sai.rx_slots = le32_to_cpu(hw_config->rx_slots); 1029 config->sai.tx_slots = le32_to_cpu(hw_config->tx_slots); 1030 1031 dev_info(scomp->dev, 1032 "tplg: config SAI%d fmt 0x%x mclk %d width %d slots %d mclk id %d\n", 1033 config->dai_index, config->format, 1034 config->sai.mclk_rate, config->sai.tdm_slot_width, 1035 config->sai.tdm_slots, config->sai.mclk_id); 1036 1037 if (config->sai.tdm_slots < 1 || config->sai.tdm_slots > 8) { 1038 dev_err(scomp->dev, "Invalid channel count for SAI%d\n", config->dai_index); 1039 return -EINVAL; 1040 } 1041 1042 dai->number_configs = 1; 1043 dai->current_config = 0; 1044 private->dai_config = kmemdup(config, size, GFP_KERNEL); 1045 if (!private->dai_config) 1046 return -ENOMEM; 1047 1048 return 0; 1049 } 1050 1051 static int sof_link_esai_load(struct snd_soc_component *scomp, struct snd_sof_dai_link *slink, 1052 struct sof_ipc_dai_config *config, struct snd_sof_dai *dai) 1053 { 1054 struct snd_soc_tplg_hw_config *hw_config = slink->hw_configs; 1055 struct sof_dai_private_data *private = dai->private; 1056 u32 size = sizeof(*config); 1057 int ret; 1058 1059 /* handle master/slave and inverted clocks */ 1060 sof_dai_set_format(hw_config, config); 1061 1062 /* init IPC */ 1063 memset(&config->esai, 0, sizeof(config->esai)); 1064 config->hdr.size = size; 1065 1066 /* parse one set of ESAI tokens */ 1067 ret = sof_update_ipc_object(scomp, &config->esai, SOF_ESAI_TOKENS, slink->tuples, 1068 slink->num_tuples, size, 1); 1069 if (ret < 0) 1070 return ret; 1071 1072 config->esai.mclk_rate = le32_to_cpu(hw_config->mclk_rate); 1073 config->esai.bclk_rate = le32_to_cpu(hw_config->bclk_rate); 1074 config->esai.fsync_rate = le32_to_cpu(hw_config->fsync_rate); 1075 config->esai.mclk_direction = hw_config->mclk_direction; 1076 config->esai.tdm_slots = le32_to_cpu(hw_config->tdm_slots); 1077 config->esai.tdm_slot_width = le32_to_cpu(hw_config->tdm_slot_width); 1078 config->esai.rx_slots = le32_to_cpu(hw_config->rx_slots); 1079 config->esai.tx_slots = le32_to_cpu(hw_config->tx_slots); 1080 1081 dev_info(scomp->dev, 1082 "tplg: config ESAI%d fmt 0x%x mclk %d width %d slots %d mclk id %d\n", 1083 config->dai_index, config->format, 1084 config->esai.mclk_rate, config->esai.tdm_slot_width, 1085 config->esai.tdm_slots, config->esai.mclk_id); 1086 1087 if (config->esai.tdm_slots < 1 || config->esai.tdm_slots > 8) { 1088 dev_err(scomp->dev, "Invalid channel count for ESAI%d\n", config->dai_index); 1089 return -EINVAL; 1090 } 1091 1092 dai->number_configs = 1; 1093 dai->current_config = 0; 1094 private->dai_config = kmemdup(config, size, GFP_KERNEL); 1095 if (!private->dai_config) 1096 return -ENOMEM; 1097 1098 return 0; 1099 } 1100 1101 static int sof_link_acp_dmic_load(struct snd_soc_component *scomp, struct snd_sof_dai_link *slink, 1102 struct sof_ipc_dai_config *config, struct snd_sof_dai *dai) 1103 { 1104 struct snd_soc_tplg_hw_config *hw_config = slink->hw_configs; 1105 struct sof_dai_private_data *private = dai->private; 1106 u32 size = sizeof(*config); 1107 1108 /* handle master/slave and inverted clocks */ 1109 sof_dai_set_format(hw_config, config); 1110 1111 /* init IPC */ 1112 memset(&config->acpdmic, 0, sizeof(config->acpdmic)); 1113 config->hdr.size = size; 1114 1115 config->acpdmic.fsync_rate = le32_to_cpu(hw_config->fsync_rate); 1116 config->acpdmic.tdm_slots = le32_to_cpu(hw_config->tdm_slots); 1117 1118 dev_info(scomp->dev, "ACP_DMIC config ACP%d channel %d rate %d\n", 1119 config->dai_index, config->acpdmic.tdm_slots, 1120 config->acpdmic.fsync_rate); 1121 1122 dai->number_configs = 1; 1123 dai->current_config = 0; 1124 private->dai_config = kmemdup(config, size, GFP_KERNEL); 1125 if (!private->dai_config) 1126 return -ENOMEM; 1127 1128 return 0; 1129 } 1130 1131 static int sof_link_acp_bt_load(struct snd_soc_component *scomp, struct snd_sof_dai_link *slink, 1132 struct sof_ipc_dai_config *config, struct snd_sof_dai *dai) 1133 { 1134 struct snd_soc_tplg_hw_config *hw_config = slink->hw_configs; 1135 struct sof_dai_private_data *private = dai->private; 1136 u32 size = sizeof(*config); 1137 1138 /* handle master/slave and inverted clocks */ 1139 sof_dai_set_format(hw_config, config); 1140 1141 /* init IPC */ 1142 memset(&config->acpbt, 0, sizeof(config->acpbt)); 1143 config->hdr.size = size; 1144 1145 config->acpbt.fsync_rate = le32_to_cpu(hw_config->fsync_rate); 1146 config->acpbt.tdm_slots = le32_to_cpu(hw_config->tdm_slots); 1147 1148 dev_info(scomp->dev, "ACP_BT config ACP%d channel %d rate %d\n", 1149 config->dai_index, config->acpbt.tdm_slots, 1150 config->acpbt.fsync_rate); 1151 1152 dai->number_configs = 1; 1153 dai->current_config = 0; 1154 private->dai_config = kmemdup(config, size, GFP_KERNEL); 1155 if (!private->dai_config) 1156 return -ENOMEM; 1157 1158 return 0; 1159 } 1160 1161 static int sof_link_acp_sp_load(struct snd_soc_component *scomp, struct snd_sof_dai_link *slink, 1162 struct sof_ipc_dai_config *config, struct snd_sof_dai *dai) 1163 { 1164 struct snd_soc_tplg_hw_config *hw_config = slink->hw_configs; 1165 struct sof_dai_private_data *private = dai->private; 1166 u32 size = sizeof(*config); 1167 1168 /* handle master/slave and inverted clocks */ 1169 sof_dai_set_format(hw_config, config); 1170 1171 /* init IPC */ 1172 memset(&config->acpsp, 0, sizeof(config->acpsp)); 1173 config->hdr.size = size; 1174 1175 config->acpsp.fsync_rate = le32_to_cpu(hw_config->fsync_rate); 1176 config->acpsp.tdm_slots = le32_to_cpu(hw_config->tdm_slots); 1177 1178 dev_info(scomp->dev, "ACP_SP config ACP%d channel %d rate %d\n", 1179 config->dai_index, config->acpsp.tdm_slots, 1180 config->acpsp.fsync_rate); 1181 1182 dai->number_configs = 1; 1183 dai->current_config = 0; 1184 private->dai_config = kmemdup(config, size, GFP_KERNEL); 1185 if (!private->dai_config) 1186 return -ENOMEM; 1187 1188 return 0; 1189 } 1190 1191 static int sof_link_afe_load(struct snd_soc_component *scomp, struct snd_sof_dai_link *slink, 1192 struct sof_ipc_dai_config *config, struct snd_sof_dai *dai) 1193 { 1194 struct sof_dai_private_data *private = dai->private; 1195 u32 size = sizeof(*config); 1196 int ret; 1197 1198 config->hdr.size = size; 1199 1200 /* parse the required set of AFE tokens based on num_hw_cfgs */ 1201 ret = sof_update_ipc_object(scomp, &config->afe, SOF_AFE_TOKENS, slink->tuples, 1202 slink->num_tuples, size, slink->num_hw_configs); 1203 if (ret < 0) 1204 return ret; 1205 1206 dev_dbg(scomp->dev, "AFE config rate %d channels %d format:%d\n", 1207 config->afe.rate, config->afe.channels, config->afe.format); 1208 1209 config->afe.stream_id = DMA_CHAN_INVALID; 1210 1211 dai->number_configs = 1; 1212 dai->current_config = 0; 1213 private->dai_config = kmemdup(config, size, GFP_KERNEL); 1214 if (!private->dai_config) 1215 return -ENOMEM; 1216 1217 return 0; 1218 } 1219 1220 static int sof_link_ssp_load(struct snd_soc_component *scomp, struct snd_sof_dai_link *slink, 1221 struct sof_ipc_dai_config *config, struct snd_sof_dai *dai) 1222 { 1223 struct snd_soc_tplg_hw_config *hw_config = slink->hw_configs; 1224 struct sof_dai_private_data *private = dai->private; 1225 u32 size = sizeof(*config); 1226 int current_config = 0; 1227 int i, ret; 1228 1229 /* 1230 * Parse common data, we should have 1 common data per hw_config. 1231 */ 1232 ret = sof_update_ipc_object(scomp, &config->ssp, SOF_SSP_TOKENS, slink->tuples, 1233 slink->num_tuples, size, slink->num_hw_configs); 1234 if (ret < 0) 1235 return ret; 1236 1237 /* process all possible hw configs */ 1238 for (i = 0; i < slink->num_hw_configs; i++) { 1239 if (le32_to_cpu(hw_config[i].id) == slink->default_hw_cfg_id) 1240 current_config = i; 1241 1242 /* handle master/slave and inverted clocks */ 1243 sof_dai_set_format(&hw_config[i], &config[i]); 1244 1245 config[i].hdr.size = size; 1246 1247 /* copy differentiating hw configs to ipc structs */ 1248 config[i].ssp.mclk_rate = le32_to_cpu(hw_config[i].mclk_rate); 1249 config[i].ssp.bclk_rate = le32_to_cpu(hw_config[i].bclk_rate); 1250 config[i].ssp.fsync_rate = le32_to_cpu(hw_config[i].fsync_rate); 1251 config[i].ssp.tdm_slots = le32_to_cpu(hw_config[i].tdm_slots); 1252 config[i].ssp.tdm_slot_width = le32_to_cpu(hw_config[i].tdm_slot_width); 1253 config[i].ssp.mclk_direction = hw_config[i].mclk_direction; 1254 config[i].ssp.rx_slots = le32_to_cpu(hw_config[i].rx_slots); 1255 config[i].ssp.tx_slots = le32_to_cpu(hw_config[i].tx_slots); 1256 1257 dev_dbg(scomp->dev, "tplg: config SSP%d fmt %#x mclk %d bclk %d fclk %d width (%d)%d slots %d mclk id %d quirks %d clks_control %#x\n", 1258 config[i].dai_index, config[i].format, 1259 config[i].ssp.mclk_rate, config[i].ssp.bclk_rate, 1260 config[i].ssp.fsync_rate, config[i].ssp.sample_valid_bits, 1261 config[i].ssp.tdm_slot_width, config[i].ssp.tdm_slots, 1262 config[i].ssp.mclk_id, config[i].ssp.quirks, config[i].ssp.clks_control); 1263 1264 /* validate SSP fsync rate and channel count */ 1265 if (config[i].ssp.fsync_rate < 8000 || config[i].ssp.fsync_rate > 192000) { 1266 dev_err(scomp->dev, "Invalid fsync rate for SSP%d\n", config[i].dai_index); 1267 return -EINVAL; 1268 } 1269 1270 if (config[i].ssp.tdm_slots < 1 || config[i].ssp.tdm_slots > 8) { 1271 dev_err(scomp->dev, "Invalid channel count for SSP%d\n", 1272 config[i].dai_index); 1273 return -EINVAL; 1274 } 1275 } 1276 1277 dai->number_configs = slink->num_hw_configs; 1278 dai->current_config = current_config; 1279 private->dai_config = kmemdup(config, size * slink->num_hw_configs, GFP_KERNEL); 1280 if (!private->dai_config) 1281 return -ENOMEM; 1282 1283 return 0; 1284 } 1285 1286 static int sof_link_dmic_load(struct snd_soc_component *scomp, struct snd_sof_dai_link *slink, 1287 struct sof_ipc_dai_config *config, struct snd_sof_dai *dai) 1288 { 1289 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 1290 struct sof_dai_private_data *private = dai->private; 1291 struct sof_ipc_fw_ready *ready = &sdev->fw_ready; 1292 struct sof_ipc_fw_version *v = &ready->version; 1293 size_t size = sizeof(*config); 1294 int i, ret; 1295 1296 /* Ensure the entire DMIC config struct is zeros */ 1297 memset(&config->dmic, 0, sizeof(config->dmic)); 1298 1299 /* parse the required set of DMIC tokens based on num_hw_cfgs */ 1300 ret = sof_update_ipc_object(scomp, &config->dmic, SOF_DMIC_TOKENS, slink->tuples, 1301 slink->num_tuples, size, slink->num_hw_configs); 1302 if (ret < 0) 1303 return ret; 1304 1305 /* parse the required set of DMIC PDM tokens based on number of active PDM's */ 1306 ret = sof_update_ipc_object(scomp, &config->dmic.pdm[0], SOF_DMIC_PDM_TOKENS, 1307 slink->tuples, slink->num_tuples, 1308 sizeof(struct sof_ipc_dai_dmic_pdm_ctrl), 1309 config->dmic.num_pdm_active); 1310 if (ret < 0) 1311 return ret; 1312 1313 /* set IPC header size */ 1314 config->hdr.size = size; 1315 1316 /* debug messages */ 1317 dev_dbg(scomp->dev, "tplg: config DMIC%d driver version %d\n", 1318 config->dai_index, config->dmic.driver_ipc_version); 1319 dev_dbg(scomp->dev, "pdmclk_min %d pdm_clkmax %d duty_min %d\n", 1320 config->dmic.pdmclk_min, config->dmic.pdmclk_max, 1321 config->dmic.duty_min); 1322 dev_dbg(scomp->dev, "duty_max %d fifo_fs %d num_pdms active %d\n", 1323 config->dmic.duty_max, config->dmic.fifo_fs, 1324 config->dmic.num_pdm_active); 1325 dev_dbg(scomp->dev, "fifo word length %d\n", config->dmic.fifo_bits); 1326 1327 for (i = 0; i < config->dmic.num_pdm_active; i++) { 1328 dev_dbg(scomp->dev, "pdm %d mic a %d mic b %d\n", 1329 config->dmic.pdm[i].id, 1330 config->dmic.pdm[i].enable_mic_a, 1331 config->dmic.pdm[i].enable_mic_b); 1332 dev_dbg(scomp->dev, "pdm %d polarity a %d polarity b %d\n", 1333 config->dmic.pdm[i].id, 1334 config->dmic.pdm[i].polarity_mic_a, 1335 config->dmic.pdm[i].polarity_mic_b); 1336 dev_dbg(scomp->dev, "pdm %d clk_edge %d skew %d\n", 1337 config->dmic.pdm[i].id, 1338 config->dmic.pdm[i].clk_edge, 1339 config->dmic.pdm[i].skew); 1340 } 1341 1342 /* 1343 * this takes care of backwards compatible handling of fifo_bits_b. 1344 * It is deprecated since firmware ABI version 3.0.1. 1345 */ 1346 if (SOF_ABI_VER(v->major, v->minor, v->micro) < SOF_ABI_VER(3, 0, 1)) 1347 config->dmic.fifo_bits_b = config->dmic.fifo_bits; 1348 1349 dai->number_configs = 1; 1350 dai->current_config = 0; 1351 private->dai_config = kmemdup(config, size, GFP_KERNEL); 1352 if (!private->dai_config) 1353 return -ENOMEM; 1354 1355 return 0; 1356 } 1357 1358 static int sof_link_alh_load(struct snd_soc_component *scomp, struct snd_sof_dai_link *slink, 1359 struct sof_ipc_dai_config *config, struct snd_sof_dai *dai) 1360 { 1361 struct sof_dai_private_data *private = dai->private; 1362 u32 size = sizeof(*config); 1363 int ret; 1364 1365 /* parse the required set of ALH tokens based on num_hw_cfgs */ 1366 ret = sof_update_ipc_object(scomp, &config->alh, SOF_ALH_TOKENS, slink->tuples, 1367 slink->num_tuples, size, slink->num_hw_configs); 1368 if (ret < 0) 1369 return ret; 1370 1371 /* init IPC */ 1372 config->hdr.size = size; 1373 1374 /* set config for all DAI's with name matching the link name */ 1375 dai->number_configs = 1; 1376 dai->current_config = 0; 1377 private->dai_config = kmemdup(config, size, GFP_KERNEL); 1378 if (!private->dai_config) 1379 return -ENOMEM; 1380 1381 return 0; 1382 } 1383 1384 static int sof_ipc3_widget_setup_comp_dai(struct snd_sof_widget *swidget) 1385 { 1386 struct snd_soc_component *scomp = swidget->scomp; 1387 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 1388 struct snd_sof_dai *dai = swidget->private; 1389 struct sof_dai_private_data *private; 1390 struct sof_ipc_comp_dai *comp_dai; 1391 size_t ipc_size = sizeof(*comp_dai); 1392 struct sof_ipc_dai_config *config; 1393 struct snd_sof_dai_link *slink; 1394 int ret; 1395 1396 private = kzalloc(sizeof(*private), GFP_KERNEL); 1397 if (!private) 1398 return -ENOMEM; 1399 1400 dai->private = private; 1401 1402 private->comp_dai = sof_comp_alloc(swidget, &ipc_size, swidget->pipeline_id); 1403 if (!private->comp_dai) { 1404 ret = -ENOMEM; 1405 goto free; 1406 } 1407 1408 /* configure dai IPC message */ 1409 comp_dai = private->comp_dai; 1410 comp_dai->comp.type = SOF_COMP_DAI; 1411 comp_dai->config.hdr.size = sizeof(comp_dai->config); 1412 1413 /* parse one set of DAI tokens */ 1414 ret = sof_update_ipc_object(scomp, comp_dai, SOF_DAI_TOKENS, swidget->tuples, 1415 swidget->num_tuples, sizeof(*comp_dai), 1); 1416 if (ret < 0) 1417 goto free; 1418 1419 /* update comp_tokens */ 1420 ret = sof_update_ipc_object(scomp, &comp_dai->config, SOF_COMP_TOKENS, 1421 swidget->tuples, swidget->num_tuples, 1422 sizeof(comp_dai->config), 1); 1423 if (ret < 0) 1424 goto free; 1425 1426 dev_dbg(scomp->dev, "%s dai %s: type %d index %d\n", 1427 __func__, swidget->widget->name, comp_dai->type, comp_dai->dai_index); 1428 sof_dbg_comp_config(scomp, &comp_dai->config); 1429 1430 /* now update DAI config */ 1431 list_for_each_entry(slink, &sdev->dai_link_list, list) { 1432 struct sof_ipc_dai_config common_config; 1433 int i; 1434 1435 if (strcmp(slink->link->name, dai->name)) 1436 continue; 1437 1438 /* Reserve memory for all hw configs, eventually freed by widget */ 1439 config = kcalloc(slink->num_hw_configs, sizeof(*config), GFP_KERNEL); 1440 if (!config) { 1441 ret = -ENOMEM; 1442 goto free_comp; 1443 } 1444 1445 /* parse one set of DAI link tokens */ 1446 ret = sof_update_ipc_object(scomp, &common_config, SOF_DAI_LINK_TOKENS, 1447 slink->tuples, slink->num_tuples, 1448 sizeof(common_config), 1); 1449 if (ret < 0) 1450 goto free_config; 1451 1452 for (i = 0; i < slink->num_hw_configs; i++) { 1453 config[i].hdr.cmd = SOF_IPC_GLB_DAI_MSG | SOF_IPC_DAI_CONFIG; 1454 config[i].format = le32_to_cpu(slink->hw_configs[i].fmt); 1455 config[i].type = common_config.type; 1456 config[i].dai_index = comp_dai->dai_index; 1457 } 1458 1459 switch (common_config.type) { 1460 case SOF_DAI_INTEL_SSP: 1461 ret = sof_link_ssp_load(scomp, slink, config, dai); 1462 break; 1463 case SOF_DAI_INTEL_DMIC: 1464 ret = sof_link_dmic_load(scomp, slink, config, dai); 1465 break; 1466 case SOF_DAI_INTEL_HDA: 1467 ret = sof_link_hda_load(scomp, slink, config, dai); 1468 break; 1469 case SOF_DAI_INTEL_ALH: 1470 ret = sof_link_alh_load(scomp, slink, config, dai); 1471 break; 1472 case SOF_DAI_IMX_SAI: 1473 ret = sof_link_sai_load(scomp, slink, config, dai); 1474 break; 1475 case SOF_DAI_IMX_ESAI: 1476 ret = sof_link_esai_load(scomp, slink, config, dai); 1477 break; 1478 case SOF_DAI_AMD_BT: 1479 ret = sof_link_acp_bt_load(scomp, slink, config, dai); 1480 break; 1481 case SOF_DAI_AMD_SP: 1482 ret = sof_link_acp_sp_load(scomp, slink, config, dai); 1483 break; 1484 case SOF_DAI_AMD_DMIC: 1485 ret = sof_link_acp_dmic_load(scomp, slink, config, dai); 1486 break; 1487 case SOF_DAI_MEDIATEK_AFE: 1488 ret = sof_link_afe_load(scomp, slink, config, dai); 1489 break; 1490 default: 1491 break; 1492 } 1493 if (ret < 0) { 1494 dev_err(scomp->dev, "failed to load config for dai %s\n", dai->name); 1495 goto free_config; 1496 } 1497 1498 kfree(config); 1499 } 1500 1501 return 0; 1502 free_config: 1503 kfree(config); 1504 free_comp: 1505 kfree(comp_dai); 1506 free: 1507 kfree(private); 1508 dai->private = NULL; 1509 return ret; 1510 } 1511 1512 static void sof_ipc3_widget_free_comp_dai(struct snd_sof_widget *swidget) 1513 { 1514 switch (swidget->id) { 1515 case snd_soc_dapm_dai_in: 1516 case snd_soc_dapm_dai_out: 1517 { 1518 struct snd_sof_dai *dai = swidget->private; 1519 struct sof_dai_private_data *dai_data; 1520 1521 if (!dai) 1522 return; 1523 1524 dai_data = dai->private; 1525 if (dai_data) { 1526 kfree(dai_data->comp_dai); 1527 kfree(dai_data->dai_config); 1528 kfree(dai_data); 1529 } 1530 kfree(dai); 1531 break; 1532 } 1533 default: 1534 break; 1535 } 1536 } 1537 1538 static int sof_ipc3_route_setup(struct snd_sof_dev *sdev, struct snd_sof_route *sroute) 1539 { 1540 struct sof_ipc_pipe_comp_connect connect; 1541 struct sof_ipc_reply reply; 1542 int ret; 1543 1544 connect.hdr.size = sizeof(connect); 1545 connect.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_CONNECT; 1546 connect.source_id = sroute->src_widget->comp_id; 1547 connect.sink_id = sroute->sink_widget->comp_id; 1548 1549 dev_dbg(sdev->dev, "setting up route %s -> %s\n", 1550 sroute->src_widget->widget->name, 1551 sroute->sink_widget->widget->name); 1552 1553 /* send ipc */ 1554 ret = sof_ipc_tx_message(sdev->ipc, connect.hdr.cmd, &connect, sizeof(connect), 1555 &reply, sizeof(reply)); 1556 if (ret < 0) 1557 dev_err(sdev->dev, "%s: route %s -> %s failed\n", __func__, 1558 sroute->src_widget->widget->name, sroute->sink_widget->widget->name); 1559 1560 return ret; 1561 } 1562 1563 static int sof_ipc3_control_load_bytes(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol) 1564 { 1565 struct sof_ipc_ctrl_data *cdata; 1566 int ret; 1567 1568 scontrol->ipc_control_data = kzalloc(scontrol->max_size, GFP_KERNEL); 1569 if (!scontrol->ipc_control_data) 1570 return -ENOMEM; 1571 1572 if (scontrol->max_size < sizeof(*cdata) || 1573 scontrol->max_size < sizeof(struct sof_abi_hdr)) { 1574 ret = -EINVAL; 1575 goto err; 1576 } 1577 1578 /* init the get/put bytes data */ 1579 if (scontrol->priv_size > scontrol->max_size - sizeof(*cdata)) { 1580 dev_err(sdev->dev, "err: bytes data size %zu exceeds max %zu.\n", 1581 scontrol->priv_size, scontrol->max_size - sizeof(*cdata)); 1582 ret = -EINVAL; 1583 goto err; 1584 } 1585 1586 scontrol->size = sizeof(struct sof_ipc_ctrl_data) + scontrol->priv_size; 1587 1588 cdata = scontrol->ipc_control_data; 1589 cdata->cmd = SOF_CTRL_CMD_BINARY; 1590 cdata->index = scontrol->index; 1591 1592 if (scontrol->priv_size > 0) { 1593 memcpy(cdata->data, scontrol->priv, scontrol->priv_size); 1594 kfree(scontrol->priv); 1595 1596 if (cdata->data->magic != SOF_ABI_MAGIC) { 1597 dev_err(sdev->dev, "Wrong ABI magic 0x%08x.\n", cdata->data->magic); 1598 ret = -EINVAL; 1599 goto err; 1600 } 1601 1602 if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION, cdata->data->abi)) { 1603 dev_err(sdev->dev, "Incompatible ABI version 0x%08x.\n", 1604 cdata->data->abi); 1605 ret = -EINVAL; 1606 goto err; 1607 } 1608 1609 if (cdata->data->size + sizeof(struct sof_abi_hdr) != scontrol->priv_size) { 1610 dev_err(sdev->dev, "Conflict in bytes vs. priv size.\n"); 1611 ret = -EINVAL; 1612 goto err; 1613 } 1614 } 1615 1616 return 0; 1617 err: 1618 kfree(scontrol->ipc_control_data); 1619 return ret; 1620 } 1621 1622 static int sof_ipc3_control_load_volume(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol) 1623 { 1624 struct sof_ipc_ctrl_data *cdata; 1625 int i; 1626 1627 /* init the volume get/put data */ 1628 scontrol->size = struct_size(cdata, chanv, scontrol->num_channels); 1629 1630 scontrol->ipc_control_data = kzalloc(scontrol->size, GFP_KERNEL); 1631 if (!scontrol->ipc_control_data) 1632 return -ENOMEM; 1633 1634 cdata = scontrol->ipc_control_data; 1635 cdata->index = scontrol->index; 1636 1637 /* set cmd for mixer control */ 1638 if (scontrol->max == 1) { 1639 cdata->cmd = SOF_CTRL_CMD_SWITCH; 1640 return 0; 1641 } 1642 1643 cdata->cmd = SOF_CTRL_CMD_VOLUME; 1644 1645 /* set default volume values to 0dB in control */ 1646 for (i = 0; i < scontrol->num_channels; i++) { 1647 cdata->chanv[i].channel = i; 1648 cdata->chanv[i].value = VOL_ZERO_DB; 1649 } 1650 1651 return 0; 1652 } 1653 1654 static int sof_ipc3_control_load_enum(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol) 1655 { 1656 struct sof_ipc_ctrl_data *cdata; 1657 1658 /* init the enum get/put data */ 1659 scontrol->size = struct_size(cdata, chanv, scontrol->num_channels); 1660 1661 scontrol->ipc_control_data = kzalloc(scontrol->size, GFP_KERNEL); 1662 if (!scontrol->ipc_control_data) 1663 return -ENOMEM; 1664 1665 cdata = scontrol->ipc_control_data; 1666 cdata->index = scontrol->index; 1667 cdata->cmd = SOF_CTRL_CMD_ENUM; 1668 1669 return 0; 1670 } 1671 1672 static int sof_ipc3_control_setup(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol) 1673 { 1674 switch (scontrol->info_type) { 1675 case SND_SOC_TPLG_CTL_VOLSW: 1676 case SND_SOC_TPLG_CTL_VOLSW_SX: 1677 case SND_SOC_TPLG_CTL_VOLSW_XR_SX: 1678 return sof_ipc3_control_load_volume(sdev, scontrol); 1679 case SND_SOC_TPLG_CTL_BYTES: 1680 return sof_ipc3_control_load_bytes(sdev, scontrol); 1681 case SND_SOC_TPLG_CTL_ENUM: 1682 case SND_SOC_TPLG_CTL_ENUM_VALUE: 1683 return sof_ipc3_control_load_enum(sdev, scontrol); 1684 default: 1685 break; 1686 } 1687 1688 return 0; 1689 } 1690 1691 static int sof_ipc3_control_free(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol) 1692 { 1693 struct sof_ipc_free fcomp; 1694 1695 fcomp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_FREE; 1696 fcomp.hdr.size = sizeof(fcomp); 1697 fcomp.id = scontrol->comp_id; 1698 1699 /* send IPC to the DSP */ 1700 return sof_ipc_tx_message(sdev->ipc, fcomp.hdr.cmd, &fcomp, sizeof(fcomp), NULL, 0); 1701 } 1702 1703 /* send pcm params ipc */ 1704 static int sof_ipc3_keyword_detect_pcm_params(struct snd_sof_widget *swidget, int dir) 1705 { 1706 struct snd_soc_component *scomp = swidget->scomp; 1707 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 1708 struct sof_ipc_pcm_params_reply ipc_params_reply; 1709 struct snd_pcm_hw_params *params; 1710 struct sof_ipc_pcm_params pcm; 1711 struct snd_sof_pcm *spcm; 1712 int ret; 1713 1714 /* get runtime PCM params using widget's stream name */ 1715 spcm = snd_sof_find_spcm_name(scomp, swidget->widget->sname); 1716 if (!spcm) { 1717 dev_err(scomp->dev, "Cannot find PCM for %s\n", swidget->widget->name); 1718 return -EINVAL; 1719 } 1720 1721 params = &spcm->params[dir]; 1722 1723 /* set IPC PCM params */ 1724 memset(&pcm, 0, sizeof(pcm)); 1725 pcm.hdr.size = sizeof(pcm); 1726 pcm.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_PCM_PARAMS; 1727 pcm.comp_id = swidget->comp_id; 1728 pcm.params.hdr.size = sizeof(pcm.params); 1729 pcm.params.direction = dir; 1730 pcm.params.sample_valid_bytes = params_width(params) >> 3; 1731 pcm.params.buffer_fmt = SOF_IPC_BUFFER_INTERLEAVED; 1732 pcm.params.rate = params_rate(params); 1733 pcm.params.channels = params_channels(params); 1734 pcm.params.host_period_bytes = params_period_bytes(params); 1735 1736 /* set format */ 1737 switch (params_format(params)) { 1738 case SNDRV_PCM_FORMAT_S16: 1739 pcm.params.frame_fmt = SOF_IPC_FRAME_S16_LE; 1740 break; 1741 case SNDRV_PCM_FORMAT_S24: 1742 pcm.params.frame_fmt = SOF_IPC_FRAME_S24_4LE; 1743 break; 1744 case SNDRV_PCM_FORMAT_S32: 1745 pcm.params.frame_fmt = SOF_IPC_FRAME_S32_LE; 1746 break; 1747 default: 1748 return -EINVAL; 1749 } 1750 1751 /* send IPC to the DSP */ 1752 ret = sof_ipc_tx_message(sdev->ipc, pcm.hdr.cmd, &pcm, sizeof(pcm), 1753 &ipc_params_reply, sizeof(ipc_params_reply)); 1754 if (ret < 0) 1755 dev_err(scomp->dev, "%s: PCM params failed for %s\n", __func__, 1756 swidget->widget->name); 1757 1758 return ret; 1759 } 1760 1761 /* send stream trigger ipc */ 1762 static int sof_ipc3_keyword_detect_trigger(struct snd_sof_widget *swidget, int cmd) 1763 { 1764 struct snd_soc_component *scomp = swidget->scomp; 1765 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 1766 struct sof_ipc_stream stream; 1767 struct sof_ipc_reply reply; 1768 int ret; 1769 1770 /* set IPC stream params */ 1771 stream.hdr.size = sizeof(stream); 1772 stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | cmd; 1773 stream.comp_id = swidget->comp_id; 1774 1775 /* send IPC to the DSP */ 1776 ret = sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream, 1777 sizeof(stream), &reply, sizeof(reply)); 1778 if (ret < 0) 1779 dev_err(scomp->dev, "%s: Failed to trigger %s\n", __func__, swidget->widget->name); 1780 1781 return ret; 1782 } 1783 1784 static int sof_ipc3_keyword_dapm_event(struct snd_soc_dapm_widget *w, 1785 struct snd_kcontrol *k, int event) 1786 { 1787 struct snd_sof_widget *swidget = w->dobj.private; 1788 struct snd_soc_component *scomp; 1789 int stream = SNDRV_PCM_STREAM_CAPTURE; 1790 struct snd_sof_pcm *spcm; 1791 int ret = 0; 1792 1793 if (!swidget) 1794 return 0; 1795 1796 scomp = swidget->scomp; 1797 1798 dev_dbg(scomp->dev, "received event %d for widget %s\n", 1799 event, w->name); 1800 1801 /* get runtime PCM params using widget's stream name */ 1802 spcm = snd_sof_find_spcm_name(scomp, swidget->widget->sname); 1803 if (!spcm) { 1804 dev_err(scomp->dev, "%s: Cannot find PCM for %s\n", __func__, 1805 swidget->widget->name); 1806 return -EINVAL; 1807 } 1808 1809 /* process events */ 1810 switch (event) { 1811 case SND_SOC_DAPM_PRE_PMU: 1812 if (spcm->stream[stream].suspend_ignored) { 1813 dev_dbg(scomp->dev, "PRE_PMU event ignored, KWD pipeline is already RUNNING\n"); 1814 return 0; 1815 } 1816 1817 /* set pcm params */ 1818 ret = sof_ipc3_keyword_detect_pcm_params(swidget, stream); 1819 if (ret < 0) { 1820 dev_err(scomp->dev, "%s: Failed to set pcm params for widget %s\n", 1821 __func__, swidget->widget->name); 1822 break; 1823 } 1824 1825 /* start trigger */ 1826 ret = sof_ipc3_keyword_detect_trigger(swidget, SOF_IPC_STREAM_TRIG_START); 1827 if (ret < 0) 1828 dev_err(scomp->dev, "%s: Failed to trigger widget %s\n", __func__, 1829 swidget->widget->name); 1830 break; 1831 case SND_SOC_DAPM_POST_PMD: 1832 if (spcm->stream[stream].suspend_ignored) { 1833 dev_dbg(scomp->dev, 1834 "POST_PMD event ignored, KWD pipeline will remain RUNNING\n"); 1835 return 0; 1836 } 1837 1838 /* stop trigger */ 1839 ret = sof_ipc3_keyword_detect_trigger(swidget, SOF_IPC_STREAM_TRIG_STOP); 1840 if (ret < 0) 1841 dev_err(scomp->dev, "%s: Failed to trigger widget %s\n", __func__, 1842 swidget->widget->name); 1843 1844 /* pcm free */ 1845 ret = sof_ipc3_keyword_detect_trigger(swidget, SOF_IPC_STREAM_PCM_FREE); 1846 if (ret < 0) 1847 dev_err(scomp->dev, "%s: Failed to free PCM for widget %s\n", __func__, 1848 swidget->widget->name); 1849 break; 1850 default: 1851 break; 1852 } 1853 1854 return ret; 1855 } 1856 1857 /* event handlers for keyword detect component */ 1858 static const struct snd_soc_tplg_widget_events sof_kwd_events[] = { 1859 {SOF_KEYWORD_DETECT_DAPM_EVENT, sof_ipc3_keyword_dapm_event}, 1860 }; 1861 1862 static int sof_ipc3_widget_bind_event(struct snd_soc_component *scomp, 1863 struct snd_sof_widget *swidget, u16 event_type) 1864 { 1865 struct sof_ipc_comp *ipc_comp; 1866 1867 /* validate widget event type */ 1868 switch (event_type) { 1869 case SOF_KEYWORD_DETECT_DAPM_EVENT: 1870 /* only KEYWORD_DETECT comps should handle this */ 1871 if (swidget->id != snd_soc_dapm_effect) 1872 break; 1873 1874 ipc_comp = swidget->private; 1875 if (ipc_comp && ipc_comp->type != SOF_COMP_KEYWORD_DETECT) 1876 break; 1877 1878 /* bind event to keyword detect comp */ 1879 return snd_soc_tplg_widget_bind_event(swidget->widget, sof_kwd_events, 1880 ARRAY_SIZE(sof_kwd_events), event_type); 1881 default: 1882 break; 1883 } 1884 1885 dev_err(scomp->dev, "Invalid event type %d for widget %s\n", event_type, 1886 swidget->widget->name); 1887 1888 return -EINVAL; 1889 } 1890 1891 static int sof_ipc3_complete_pipeline(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) 1892 { 1893 struct sof_ipc_pipe_ready ready; 1894 struct sof_ipc_reply reply; 1895 int ret; 1896 1897 dev_dbg(sdev->dev, "tplg: complete pipeline %s id %d\n", 1898 swidget->widget->name, swidget->comp_id); 1899 1900 memset(&ready, 0, sizeof(ready)); 1901 ready.hdr.size = sizeof(ready); 1902 ready.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_PIPE_COMPLETE; 1903 ready.comp_id = swidget->comp_id; 1904 1905 ret = sof_ipc_tx_message(sdev->ipc, ready.hdr.cmd, &ready, sizeof(ready), &reply, 1906 sizeof(reply)); 1907 if (ret < 0) 1908 return ret; 1909 1910 return 1; 1911 } 1912 1913 static int sof_ipc3_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) 1914 { 1915 struct sof_ipc_free ipc_free = { 1916 .hdr = { 1917 .size = sizeof(ipc_free), 1918 .cmd = SOF_IPC_GLB_TPLG_MSG, 1919 }, 1920 .id = swidget->comp_id, 1921 }; 1922 struct sof_ipc_reply reply; 1923 int ret; 1924 1925 if (!swidget->private) 1926 return 0; 1927 1928 switch (swidget->id) { 1929 case snd_soc_dapm_scheduler: 1930 { 1931 ipc_free.hdr.cmd |= SOF_IPC_TPLG_PIPE_FREE; 1932 break; 1933 } 1934 case snd_soc_dapm_buffer: 1935 ipc_free.hdr.cmd |= SOF_IPC_TPLG_BUFFER_FREE; 1936 break; 1937 default: 1938 ipc_free.hdr.cmd |= SOF_IPC_TPLG_COMP_FREE; 1939 break; 1940 } 1941 1942 ret = sof_ipc_tx_message(sdev->ipc, ipc_free.hdr.cmd, &ipc_free, sizeof(ipc_free), 1943 &reply, sizeof(reply)); 1944 if (ret < 0) 1945 dev_err(sdev->dev, "failed to free widget %s\n", swidget->widget->name); 1946 1947 return ret; 1948 } 1949 1950 static int sof_ipc3_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget, 1951 unsigned int flags, struct snd_sof_dai_config_data *data) 1952 { 1953 struct sof_ipc_fw_version *v = &sdev->fw_ready.version; 1954 struct snd_sof_dai *dai = swidget->private; 1955 struct sof_dai_private_data *private; 1956 struct sof_ipc_dai_config *config; 1957 struct sof_ipc_reply reply; 1958 int ret = 0; 1959 1960 if (!dai || !dai->private) { 1961 dev_err(sdev->dev, "No private data for DAI %s\n", swidget->widget->name); 1962 return -EINVAL; 1963 } 1964 1965 private = dai->private; 1966 if (!private->dai_config) { 1967 dev_err(sdev->dev, "No config for DAI %s\n", dai->name); 1968 return -EINVAL; 1969 } 1970 1971 config = &private->dai_config[dai->current_config]; 1972 if (!config) { 1973 dev_err(sdev->dev, "Invalid current config for DAI %s\n", dai->name); 1974 return -EINVAL; 1975 } 1976 1977 switch (config->type) { 1978 case SOF_DAI_INTEL_SSP: 1979 /* 1980 * DAI_CONFIG IPC during hw_params/hw_free for SSP DAI's is not supported in older 1981 * firmware 1982 */ 1983 if (v->abi_version < SOF_ABI_VER(3, 18, 0) && 1984 ((flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS) || 1985 (flags & SOF_DAI_CONFIG_FLAGS_HW_FREE))) 1986 return 0; 1987 break; 1988 case SOF_DAI_INTEL_HDA: 1989 if (data) 1990 config->hda.link_dma_ch = data->dai_data; 1991 break; 1992 case SOF_DAI_INTEL_ALH: 1993 if (data) { 1994 config->dai_index = data->dai_index; 1995 config->alh.stream_id = data->dai_data; 1996 } 1997 break; 1998 default: 1999 break; 2000 } 2001 2002 config->flags = flags; 2003 2004 /* only send the IPC if the widget is set up in the DSP */ 2005 if (swidget->use_count > 0) { 2006 ret = sof_ipc_tx_message(sdev->ipc, config->hdr.cmd, config, config->hdr.size, 2007 &reply, sizeof(reply)); 2008 if (ret < 0) 2009 dev_err(sdev->dev, "Failed to set dai config for %s\n", dai->name); 2010 } 2011 2012 return ret; 2013 } 2014 2015 static int sof_ipc3_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) 2016 { 2017 struct sof_ipc_comp_reply reply; 2018 int ret; 2019 2020 if (!swidget->private) 2021 return 0; 2022 2023 switch (swidget->id) { 2024 case snd_soc_dapm_dai_in: 2025 case snd_soc_dapm_dai_out: 2026 { 2027 struct snd_sof_dai *dai = swidget->private; 2028 struct sof_dai_private_data *dai_data = dai->private; 2029 struct sof_ipc_comp *comp = &dai_data->comp_dai->comp; 2030 2031 ret = sof_ipc_tx_message(sdev->ipc, comp->hdr.cmd, dai_data->comp_dai, 2032 comp->hdr.size, &reply, sizeof(reply)); 2033 break; 2034 } 2035 case snd_soc_dapm_scheduler: 2036 { 2037 struct sof_ipc_pipe_new *pipeline; 2038 2039 pipeline = swidget->private; 2040 ret = sof_ipc_tx_message(sdev->ipc, pipeline->hdr.cmd, pipeline, 2041 sizeof(*pipeline), &reply, sizeof(reply)); 2042 break; 2043 } 2044 default: 2045 { 2046 struct sof_ipc_cmd_hdr *hdr; 2047 2048 hdr = swidget->private; 2049 ret = sof_ipc_tx_message(sdev->ipc, hdr->cmd, swidget->private, hdr->size, 2050 &reply, sizeof(reply)); 2051 break; 2052 } 2053 } 2054 if (ret < 0) 2055 dev_err(sdev->dev, "Failed to setup widget %s\n", swidget->widget->name); 2056 2057 return ret; 2058 } 2059 2060 static int sof_ipc3_set_up_all_pipelines(struct snd_sof_dev *sdev, bool verify) 2061 { 2062 struct sof_ipc_fw_version *v = &sdev->fw_ready.version; 2063 struct snd_sof_widget *swidget; 2064 struct snd_sof_route *sroute; 2065 int ret; 2066 2067 /* restore pipeline components */ 2068 list_for_each_entry(swidget, &sdev->widget_list, list) { 2069 /* only set up the widgets belonging to static pipelines */ 2070 if (!verify && swidget->dynamic_pipeline_widget) 2071 continue; 2072 2073 /* 2074 * For older firmware, skip scheduler widgets in this loop, 2075 * sof_widget_setup() will be called in the 'complete pipeline' loop 2076 */ 2077 if (v->abi_version < SOF_ABI_VER(3, 19, 0) && 2078 swidget->id == snd_soc_dapm_scheduler) 2079 continue; 2080 2081 /* update DAI config. The IPC will be sent in sof_widget_setup() */ 2082 if (WIDGET_IS_DAI(swidget->id)) { 2083 struct snd_sof_dai *dai = swidget->private; 2084 struct sof_dai_private_data *private; 2085 struct sof_ipc_dai_config *config; 2086 2087 if (!dai || !dai->private) 2088 continue; 2089 private = dai->private; 2090 if (!private->dai_config) 2091 continue; 2092 2093 config = private->dai_config; 2094 /* 2095 * The link DMA channel would be invalidated for running 2096 * streams but not for streams that were in the PAUSED 2097 * state during suspend. So invalidate it here before setting 2098 * the dai config in the DSP. 2099 */ 2100 if (config->type == SOF_DAI_INTEL_HDA) 2101 config->hda.link_dma_ch = DMA_CHAN_INVALID; 2102 } 2103 2104 ret = sof_widget_setup(sdev, swidget); 2105 if (ret < 0) 2106 return ret; 2107 } 2108 2109 /* restore pipeline connections */ 2110 list_for_each_entry(sroute, &sdev->route_list, list) { 2111 /* only set up routes belonging to static pipelines */ 2112 if (!verify && (sroute->src_widget->dynamic_pipeline_widget || 2113 sroute->sink_widget->dynamic_pipeline_widget)) 2114 continue; 2115 2116 /* 2117 * For virtual routes, both sink and source are not buffer. IPC3 only supports 2118 * connections between a buffer and a component. Ignore the rest. 2119 */ 2120 if (sroute->src_widget->id != snd_soc_dapm_buffer && 2121 sroute->sink_widget->id != snd_soc_dapm_buffer) 2122 continue; 2123 2124 ret = sof_route_setup(sdev, sroute->src_widget->widget, 2125 sroute->sink_widget->widget); 2126 if (ret < 0) { 2127 dev_err(sdev->dev, "%s: route set up failed\n", __func__); 2128 return ret; 2129 } 2130 } 2131 2132 /* complete pipeline */ 2133 list_for_each_entry(swidget, &sdev->widget_list, list) { 2134 switch (swidget->id) { 2135 case snd_soc_dapm_scheduler: 2136 /* only complete static pipelines */ 2137 if (!verify && swidget->dynamic_pipeline_widget) 2138 continue; 2139 2140 if (v->abi_version < SOF_ABI_VER(3, 19, 0)) { 2141 ret = sof_widget_setup(sdev, swidget); 2142 if (ret < 0) 2143 return ret; 2144 } 2145 2146 swidget->complete = sof_ipc3_complete_pipeline(sdev, swidget); 2147 if (swidget->complete < 0) 2148 return swidget->complete; 2149 break; 2150 default: 2151 break; 2152 } 2153 } 2154 2155 return 0; 2156 } 2157 2158 /* 2159 * Free the PCM, its associated widgets and set the prepared flag to false for all PCMs that 2160 * did not get suspended(ex: paused streams) so the widgets can be set up again during resume. 2161 */ 2162 static int sof_tear_down_left_over_pipelines(struct snd_sof_dev *sdev) 2163 { 2164 struct snd_sof_widget *swidget; 2165 struct snd_sof_pcm *spcm; 2166 int dir, ret; 2167 2168 /* 2169 * free all PCMs and their associated DAPM widgets if their connected DAPM widget 2170 * list is not NULL. This should only be true for paused streams at this point. 2171 * This is equivalent to the handling of FE DAI suspend trigger for running streams. 2172 */ 2173 list_for_each_entry(spcm, &sdev->pcm_list, list) { 2174 for_each_pcm_streams(dir) { 2175 struct snd_pcm_substream *substream = spcm->stream[dir].substream; 2176 2177 if (!substream || !substream->runtime) 2178 continue; 2179 2180 if (spcm->stream[dir].list) { 2181 ret = sof_pcm_stream_free(sdev, substream, spcm, dir, true); 2182 if (ret < 0) 2183 return ret; 2184 } 2185 } 2186 } 2187 2188 /* 2189 * free any left over DAI widgets. This is equivalent to the handling of suspend trigger 2190 * for the BE DAI for running streams. 2191 */ 2192 list_for_each_entry(swidget, &sdev->widget_list, list) 2193 if (WIDGET_IS_DAI(swidget->id) && swidget->use_count == 1) { 2194 ret = sof_widget_free(sdev, swidget); 2195 if (ret < 0) 2196 return ret; 2197 } 2198 2199 return 0; 2200 } 2201 2202 /* 2203 * For older firmware, this function doesn't free widgets for static pipelines during suspend. 2204 * It only resets use_count for all widgets. 2205 */ 2206 static int sof_ipc3_tear_down_all_pipelines(struct snd_sof_dev *sdev, bool verify) 2207 { 2208 struct sof_ipc_fw_version *v = &sdev->fw_ready.version; 2209 struct snd_sof_widget *swidget; 2210 struct snd_sof_route *sroute; 2211 int ret; 2212 2213 /* 2214 * This function is called during suspend and for one-time topology verification during 2215 * first boot. In both cases, there is no need to protect swidget->use_count and 2216 * sroute->setup because during suspend all running streams are suspended and during 2217 * topology loading the sound card unavailable to open PCMs. 2218 */ 2219 list_for_each_entry(swidget, &sdev->widget_list, list) { 2220 if (swidget->dynamic_pipeline_widget) 2221 continue; 2222 2223 /* Do not free widgets for static pipelines with FW ABI older than 3.19 */ 2224 if (!verify && !swidget->dynamic_pipeline_widget && 2225 v->abi_version < SOF_ABI_VER(3, 19, 0)) { 2226 swidget->use_count = 0; 2227 swidget->complete = 0; 2228 continue; 2229 } 2230 2231 ret = sof_widget_free(sdev, swidget); 2232 if (ret < 0) 2233 return ret; 2234 } 2235 2236 /* 2237 * Tear down all pipelines associated with PCMs that did not get suspended 2238 * and unset the prepare flag so that they can be set up again during resume. 2239 * Skip this step for older firmware. 2240 */ 2241 if (!verify && v->abi_version >= SOF_ABI_VER(3, 19, 0)) { 2242 ret = sof_tear_down_left_over_pipelines(sdev); 2243 if (ret < 0) { 2244 dev_err(sdev->dev, "failed to tear down paused pipelines\n"); 2245 return ret; 2246 } 2247 } 2248 2249 list_for_each_entry(sroute, &sdev->route_list, list) 2250 sroute->setup = false; 2251 2252 return 0; 2253 } 2254 2255 static int sof_ipc3_dai_get_clk(struct snd_sof_dev *sdev, struct snd_sof_dai *dai, int clk_type) 2256 { 2257 struct sof_dai_private_data *private = dai->private; 2258 2259 if (!private || !private->dai_config) 2260 return 0; 2261 2262 switch (private->dai_config->type) { 2263 case SOF_DAI_INTEL_SSP: 2264 switch (clk_type) { 2265 case SOF_DAI_CLK_INTEL_SSP_MCLK: 2266 return private->dai_config->ssp.mclk_rate; 2267 case SOF_DAI_CLK_INTEL_SSP_BCLK: 2268 return private->dai_config->ssp.bclk_rate; 2269 default: 2270 break; 2271 } 2272 dev_err(sdev->dev, "fail to get SSP clk %d rate\n", clk_type); 2273 break; 2274 default: 2275 /* not yet implemented for platforms other than the above */ 2276 dev_err(sdev->dev, "DAI type %d not supported yet!\n", private->dai_config->type); 2277 break; 2278 } 2279 2280 return -EINVAL; 2281 } 2282 2283 /* token list for each topology object */ 2284 static enum sof_tokens host_token_list[] = { 2285 SOF_CORE_TOKENS, 2286 SOF_COMP_EXT_TOKENS, 2287 SOF_PCM_TOKENS, 2288 SOF_COMP_TOKENS, 2289 }; 2290 2291 static enum sof_tokens comp_generic_token_list[] = { 2292 SOF_CORE_TOKENS, 2293 SOF_COMP_EXT_TOKENS, 2294 SOF_COMP_TOKENS, 2295 }; 2296 2297 static enum sof_tokens buffer_token_list[] = { 2298 SOF_BUFFER_TOKENS, 2299 }; 2300 2301 static enum sof_tokens pipeline_token_list[] = { 2302 SOF_CORE_TOKENS, 2303 SOF_COMP_EXT_TOKENS, 2304 SOF_PIPELINE_TOKENS, 2305 SOF_SCHED_TOKENS, 2306 }; 2307 2308 static enum sof_tokens asrc_token_list[] = { 2309 SOF_CORE_TOKENS, 2310 SOF_COMP_EXT_TOKENS, 2311 SOF_ASRC_TOKENS, 2312 SOF_COMP_TOKENS, 2313 }; 2314 2315 static enum sof_tokens src_token_list[] = { 2316 SOF_CORE_TOKENS, 2317 SOF_COMP_EXT_TOKENS, 2318 SOF_SRC_TOKENS, 2319 SOF_COMP_TOKENS 2320 }; 2321 2322 static enum sof_tokens pga_token_list[] = { 2323 SOF_CORE_TOKENS, 2324 SOF_COMP_EXT_TOKENS, 2325 SOF_VOLUME_TOKENS, 2326 SOF_COMP_TOKENS, 2327 }; 2328 2329 static enum sof_tokens dai_token_list[] = { 2330 SOF_CORE_TOKENS, 2331 SOF_COMP_EXT_TOKENS, 2332 SOF_DAI_TOKENS, 2333 SOF_COMP_TOKENS, 2334 }; 2335 2336 static enum sof_tokens process_token_list[] = { 2337 SOF_CORE_TOKENS, 2338 SOF_COMP_EXT_TOKENS, 2339 SOF_PROCESS_TOKENS, 2340 SOF_COMP_TOKENS, 2341 }; 2342 2343 static const struct sof_ipc_tplg_widget_ops tplg_ipc3_widget_ops[SND_SOC_DAPM_TYPE_COUNT] = { 2344 [snd_soc_dapm_aif_in] = {sof_ipc3_widget_setup_comp_host, sof_ipc3_widget_free_comp, 2345 host_token_list, ARRAY_SIZE(host_token_list), NULL}, 2346 [snd_soc_dapm_aif_out] = {sof_ipc3_widget_setup_comp_host, sof_ipc3_widget_free_comp, 2347 host_token_list, ARRAY_SIZE(host_token_list), NULL}, 2348 2349 [snd_soc_dapm_dai_in] = {sof_ipc3_widget_setup_comp_dai, sof_ipc3_widget_free_comp_dai, 2350 dai_token_list, ARRAY_SIZE(dai_token_list), NULL}, 2351 [snd_soc_dapm_dai_out] = {sof_ipc3_widget_setup_comp_dai, sof_ipc3_widget_free_comp_dai, 2352 dai_token_list, ARRAY_SIZE(dai_token_list), NULL}, 2353 [snd_soc_dapm_buffer] = {sof_ipc3_widget_setup_comp_buffer, sof_ipc3_widget_free_comp, 2354 buffer_token_list, ARRAY_SIZE(buffer_token_list), NULL}, 2355 [snd_soc_dapm_mixer] = {sof_ipc3_widget_setup_comp_mixer, sof_ipc3_widget_free_comp, 2356 comp_generic_token_list, ARRAY_SIZE(comp_generic_token_list), 2357 NULL}, 2358 [snd_soc_dapm_src] = {sof_ipc3_widget_setup_comp_src, sof_ipc3_widget_free_comp, 2359 src_token_list, ARRAY_SIZE(src_token_list), NULL}, 2360 [snd_soc_dapm_asrc] = {sof_ipc3_widget_setup_comp_asrc, sof_ipc3_widget_free_comp, 2361 asrc_token_list, ARRAY_SIZE(asrc_token_list), NULL}, 2362 [snd_soc_dapm_siggen] = {sof_ipc3_widget_setup_comp_tone, sof_ipc3_widget_free_comp, 2363 comp_generic_token_list, ARRAY_SIZE(comp_generic_token_list), 2364 NULL}, 2365 [snd_soc_dapm_scheduler] = {sof_ipc3_widget_setup_comp_pipeline, sof_ipc3_widget_free_comp, 2366 pipeline_token_list, ARRAY_SIZE(pipeline_token_list), NULL}, 2367 [snd_soc_dapm_pga] = {sof_ipc3_widget_setup_comp_pga, sof_ipc3_widget_free_comp, 2368 pga_token_list, ARRAY_SIZE(pga_token_list), NULL}, 2369 [snd_soc_dapm_mux] = {sof_ipc3_widget_setup_comp_mux, sof_ipc3_widget_free_comp, 2370 comp_generic_token_list, ARRAY_SIZE(comp_generic_token_list), NULL}, 2371 [snd_soc_dapm_demux] = {sof_ipc3_widget_setup_comp_mux, sof_ipc3_widget_free_comp, 2372 comp_generic_token_list, ARRAY_SIZE(comp_generic_token_list), 2373 NULL}, 2374 [snd_soc_dapm_effect] = {sof_widget_update_ipc_comp_process, sof_ipc3_widget_free_comp, 2375 process_token_list, ARRAY_SIZE(process_token_list), 2376 sof_ipc3_widget_bind_event}, 2377 }; 2378 2379 const struct sof_ipc_tplg_ops ipc3_tplg_ops = { 2380 .widget = tplg_ipc3_widget_ops, 2381 .control = &tplg_ipc3_control_ops, 2382 .route_setup = sof_ipc3_route_setup, 2383 .control_setup = sof_ipc3_control_setup, 2384 .control_free = sof_ipc3_control_free, 2385 .pipeline_complete = sof_ipc3_complete_pipeline, 2386 .token_list = ipc3_token_list, 2387 .widget_free = sof_ipc3_widget_free, 2388 .widget_setup = sof_ipc3_widget_setup, 2389 .dai_config = sof_ipc3_dai_config, 2390 .dai_get_clk = sof_ipc3_dai_get_clk, 2391 .set_up_all_pipelines = sof_ipc3_set_up_all_pipelines, 2392 .tear_down_all_pipelines = sof_ipc3_tear_down_all_pipelines, 2393 }; 2394