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, sizeof(connect), &reply, sizeof(reply)); 1555 if (ret < 0) 1556 dev_err(sdev->dev, "%s: route %s -> %s failed\n", __func__, 1557 sroute->src_widget->widget->name, sroute->sink_widget->widget->name); 1558 1559 return ret; 1560 } 1561 1562 static int sof_ipc3_control_load_bytes(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol) 1563 { 1564 struct sof_ipc_ctrl_data *cdata; 1565 int ret; 1566 1567 scontrol->ipc_control_data = kzalloc(scontrol->max_size, GFP_KERNEL); 1568 if (!scontrol->ipc_control_data) 1569 return -ENOMEM; 1570 1571 if (scontrol->max_size < sizeof(*cdata) || 1572 scontrol->max_size < sizeof(struct sof_abi_hdr)) { 1573 ret = -EINVAL; 1574 goto err; 1575 } 1576 1577 /* init the get/put bytes data */ 1578 if (scontrol->priv_size > scontrol->max_size - sizeof(*cdata)) { 1579 dev_err(sdev->dev, "err: bytes data size %zu exceeds max %zu.\n", 1580 scontrol->priv_size, scontrol->max_size - sizeof(*cdata)); 1581 ret = -EINVAL; 1582 goto err; 1583 } 1584 1585 scontrol->size = sizeof(struct sof_ipc_ctrl_data) + scontrol->priv_size; 1586 1587 cdata = scontrol->ipc_control_data; 1588 cdata->cmd = SOF_CTRL_CMD_BINARY; 1589 cdata->index = scontrol->index; 1590 1591 if (scontrol->priv_size > 0) { 1592 memcpy(cdata->data, scontrol->priv, scontrol->priv_size); 1593 kfree(scontrol->priv); 1594 scontrol->priv = NULL; 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, 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, 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, sizeof(stream), &reply, sizeof(reply)); 1777 if (ret < 0) 1778 dev_err(scomp->dev, "%s: Failed to trigger %s\n", __func__, swidget->widget->name); 1779 1780 return ret; 1781 } 1782 1783 static int sof_ipc3_keyword_dapm_event(struct snd_soc_dapm_widget *w, 1784 struct snd_kcontrol *k, int event) 1785 { 1786 struct snd_sof_widget *swidget = w->dobj.private; 1787 struct snd_soc_component *scomp; 1788 int stream = SNDRV_PCM_STREAM_CAPTURE; 1789 struct snd_sof_pcm *spcm; 1790 int ret = 0; 1791 1792 if (!swidget) 1793 return 0; 1794 1795 scomp = swidget->scomp; 1796 1797 dev_dbg(scomp->dev, "received event %d for widget %s\n", 1798 event, w->name); 1799 1800 /* get runtime PCM params using widget's stream name */ 1801 spcm = snd_sof_find_spcm_name(scomp, swidget->widget->sname); 1802 if (!spcm) { 1803 dev_err(scomp->dev, "%s: Cannot find PCM for %s\n", __func__, 1804 swidget->widget->name); 1805 return -EINVAL; 1806 } 1807 1808 /* process events */ 1809 switch (event) { 1810 case SND_SOC_DAPM_PRE_PMU: 1811 if (spcm->stream[stream].suspend_ignored) { 1812 dev_dbg(scomp->dev, "PRE_PMU event ignored, KWD pipeline is already RUNNING\n"); 1813 return 0; 1814 } 1815 1816 /* set pcm params */ 1817 ret = sof_ipc3_keyword_detect_pcm_params(swidget, stream); 1818 if (ret < 0) { 1819 dev_err(scomp->dev, "%s: Failed to set pcm params for widget %s\n", 1820 __func__, swidget->widget->name); 1821 break; 1822 } 1823 1824 /* start trigger */ 1825 ret = sof_ipc3_keyword_detect_trigger(swidget, SOF_IPC_STREAM_TRIG_START); 1826 if (ret < 0) 1827 dev_err(scomp->dev, "%s: Failed to trigger widget %s\n", __func__, 1828 swidget->widget->name); 1829 break; 1830 case SND_SOC_DAPM_POST_PMD: 1831 if (spcm->stream[stream].suspend_ignored) { 1832 dev_dbg(scomp->dev, 1833 "POST_PMD event ignored, KWD pipeline will remain RUNNING\n"); 1834 return 0; 1835 } 1836 1837 /* stop trigger */ 1838 ret = sof_ipc3_keyword_detect_trigger(swidget, SOF_IPC_STREAM_TRIG_STOP); 1839 if (ret < 0) 1840 dev_err(scomp->dev, "%s: Failed to trigger widget %s\n", __func__, 1841 swidget->widget->name); 1842 1843 /* pcm free */ 1844 ret = sof_ipc3_keyword_detect_trigger(swidget, SOF_IPC_STREAM_PCM_FREE); 1845 if (ret < 0) 1846 dev_err(scomp->dev, "%s: Failed to free PCM for widget %s\n", __func__, 1847 swidget->widget->name); 1848 break; 1849 default: 1850 break; 1851 } 1852 1853 return ret; 1854 } 1855 1856 /* event handlers for keyword detect component */ 1857 static const struct snd_soc_tplg_widget_events sof_kwd_events[] = { 1858 {SOF_KEYWORD_DETECT_DAPM_EVENT, sof_ipc3_keyword_dapm_event}, 1859 }; 1860 1861 static int sof_ipc3_widget_bind_event(struct snd_soc_component *scomp, 1862 struct snd_sof_widget *swidget, u16 event_type) 1863 { 1864 struct sof_ipc_comp *ipc_comp; 1865 1866 /* validate widget event type */ 1867 switch (event_type) { 1868 case SOF_KEYWORD_DETECT_DAPM_EVENT: 1869 /* only KEYWORD_DETECT comps should handle this */ 1870 if (swidget->id != snd_soc_dapm_effect) 1871 break; 1872 1873 ipc_comp = swidget->private; 1874 if (ipc_comp && ipc_comp->type != SOF_COMP_KEYWORD_DETECT) 1875 break; 1876 1877 /* bind event to keyword detect comp */ 1878 return snd_soc_tplg_widget_bind_event(swidget->widget, sof_kwd_events, 1879 ARRAY_SIZE(sof_kwd_events), event_type); 1880 default: 1881 break; 1882 } 1883 1884 dev_err(scomp->dev, "Invalid event type %d for widget %s\n", event_type, 1885 swidget->widget->name); 1886 1887 return -EINVAL; 1888 } 1889 1890 static int sof_ipc3_complete_pipeline(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) 1891 { 1892 struct sof_ipc_pipe_ready ready; 1893 struct sof_ipc_reply reply; 1894 int ret; 1895 1896 dev_dbg(sdev->dev, "tplg: complete pipeline %s id %d\n", 1897 swidget->widget->name, swidget->comp_id); 1898 1899 memset(&ready, 0, sizeof(ready)); 1900 ready.hdr.size = sizeof(ready); 1901 ready.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_PIPE_COMPLETE; 1902 ready.comp_id = swidget->comp_id; 1903 1904 ret = sof_ipc_tx_message(sdev->ipc, &ready, sizeof(ready), &reply, sizeof(reply)); 1905 if (ret < 0) 1906 return ret; 1907 1908 return 1; 1909 } 1910 1911 static int sof_ipc3_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) 1912 { 1913 struct sof_ipc_free ipc_free = { 1914 .hdr = { 1915 .size = sizeof(ipc_free), 1916 .cmd = SOF_IPC_GLB_TPLG_MSG, 1917 }, 1918 .id = swidget->comp_id, 1919 }; 1920 struct sof_ipc_reply reply; 1921 int ret; 1922 1923 if (!swidget->private) 1924 return 0; 1925 1926 switch (swidget->id) { 1927 case snd_soc_dapm_scheduler: 1928 { 1929 ipc_free.hdr.cmd |= SOF_IPC_TPLG_PIPE_FREE; 1930 break; 1931 } 1932 case snd_soc_dapm_buffer: 1933 ipc_free.hdr.cmd |= SOF_IPC_TPLG_BUFFER_FREE; 1934 break; 1935 default: 1936 ipc_free.hdr.cmd |= SOF_IPC_TPLG_COMP_FREE; 1937 break; 1938 } 1939 1940 ret = sof_ipc_tx_message(sdev->ipc, &ipc_free, sizeof(ipc_free), 1941 &reply, sizeof(reply)); 1942 if (ret < 0) 1943 dev_err(sdev->dev, "failed to free widget %s\n", swidget->widget->name); 1944 1945 return ret; 1946 } 1947 1948 static int sof_ipc3_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget, 1949 unsigned int flags, struct snd_sof_dai_config_data *data) 1950 { 1951 struct sof_ipc_fw_version *v = &sdev->fw_ready.version; 1952 struct snd_sof_dai *dai = swidget->private; 1953 struct sof_dai_private_data *private; 1954 struct sof_ipc_dai_config *config; 1955 struct sof_ipc_reply reply; 1956 int ret = 0; 1957 1958 if (!dai || !dai->private) { 1959 dev_err(sdev->dev, "No private data for DAI %s\n", swidget->widget->name); 1960 return -EINVAL; 1961 } 1962 1963 private = dai->private; 1964 if (!private->dai_config) { 1965 dev_err(sdev->dev, "No config for DAI %s\n", dai->name); 1966 return -EINVAL; 1967 } 1968 1969 config = &private->dai_config[dai->current_config]; 1970 if (!config) { 1971 dev_err(sdev->dev, "Invalid current config for DAI %s\n", dai->name); 1972 return -EINVAL; 1973 } 1974 1975 switch (config->type) { 1976 case SOF_DAI_INTEL_SSP: 1977 /* 1978 * DAI_CONFIG IPC during hw_params/hw_free for SSP DAI's is not supported in older 1979 * firmware 1980 */ 1981 if (v->abi_version < SOF_ABI_VER(3, 18, 0) && 1982 ((flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS) || 1983 (flags & SOF_DAI_CONFIG_FLAGS_HW_FREE))) 1984 return 0; 1985 break; 1986 case SOF_DAI_INTEL_HDA: 1987 if (data) 1988 config->hda.link_dma_ch = data->dai_data; 1989 break; 1990 case SOF_DAI_INTEL_ALH: 1991 if (data) { 1992 config->dai_index = data->dai_index; 1993 config->alh.stream_id = data->dai_data; 1994 } 1995 break; 1996 default: 1997 break; 1998 } 1999 2000 config->flags = flags; 2001 2002 /* only send the IPC if the widget is set up in the DSP */ 2003 if (swidget->use_count > 0) { 2004 ret = sof_ipc_tx_message(sdev->ipc, config, config->hdr.size, 2005 &reply, sizeof(reply)); 2006 if (ret < 0) 2007 dev_err(sdev->dev, "Failed to set dai config for %s\n", dai->name); 2008 } 2009 2010 return ret; 2011 } 2012 2013 static int sof_ipc3_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) 2014 { 2015 struct sof_ipc_comp_reply reply; 2016 int ret; 2017 2018 if (!swidget->private) 2019 return 0; 2020 2021 switch (swidget->id) { 2022 case snd_soc_dapm_dai_in: 2023 case snd_soc_dapm_dai_out: 2024 { 2025 struct snd_sof_dai *dai = swidget->private; 2026 struct sof_dai_private_data *dai_data = dai->private; 2027 struct sof_ipc_comp *comp = &dai_data->comp_dai->comp; 2028 2029 ret = sof_ipc_tx_message(sdev->ipc, dai_data->comp_dai, 2030 comp->hdr.size, &reply, sizeof(reply)); 2031 break; 2032 } 2033 case snd_soc_dapm_scheduler: 2034 { 2035 struct sof_ipc_pipe_new *pipeline; 2036 2037 pipeline = swidget->private; 2038 ret = sof_ipc_tx_message(sdev->ipc, pipeline, sizeof(*pipeline), 2039 &reply, sizeof(reply)); 2040 break; 2041 } 2042 default: 2043 { 2044 struct sof_ipc_cmd_hdr *hdr; 2045 2046 hdr = swidget->private; 2047 ret = sof_ipc_tx_message(sdev->ipc, swidget->private, hdr->size, 2048 &reply, sizeof(reply)); 2049 break; 2050 } 2051 } 2052 if (ret < 0) 2053 dev_err(sdev->dev, "Failed to setup widget %s\n", swidget->widget->name); 2054 2055 return ret; 2056 } 2057 2058 static int sof_ipc3_set_up_all_pipelines(struct snd_sof_dev *sdev, bool verify) 2059 { 2060 struct sof_ipc_fw_version *v = &sdev->fw_ready.version; 2061 struct snd_sof_widget *swidget; 2062 struct snd_sof_route *sroute; 2063 int ret; 2064 2065 /* restore pipeline components */ 2066 list_for_each_entry(swidget, &sdev->widget_list, list) { 2067 /* only set up the widgets belonging to static pipelines */ 2068 if (!verify && swidget->dynamic_pipeline_widget) 2069 continue; 2070 2071 /* 2072 * For older firmware, skip scheduler widgets in this loop, 2073 * sof_widget_setup() will be called in the 'complete pipeline' loop 2074 */ 2075 if (v->abi_version < SOF_ABI_VER(3, 19, 0) && 2076 swidget->id == snd_soc_dapm_scheduler) 2077 continue; 2078 2079 /* update DAI config. The IPC will be sent in sof_widget_setup() */ 2080 if (WIDGET_IS_DAI(swidget->id)) { 2081 struct snd_sof_dai *dai = swidget->private; 2082 struct sof_dai_private_data *private; 2083 struct sof_ipc_dai_config *config; 2084 2085 if (!dai || !dai->private) 2086 continue; 2087 private = dai->private; 2088 if (!private->dai_config) 2089 continue; 2090 2091 config = private->dai_config; 2092 /* 2093 * The link DMA channel would be invalidated for running 2094 * streams but not for streams that were in the PAUSED 2095 * state during suspend. So invalidate it here before setting 2096 * the dai config in the DSP. 2097 */ 2098 if (config->type == SOF_DAI_INTEL_HDA) 2099 config->hda.link_dma_ch = DMA_CHAN_INVALID; 2100 } 2101 2102 ret = sof_widget_setup(sdev, swidget); 2103 if (ret < 0) 2104 return ret; 2105 } 2106 2107 /* restore pipeline connections */ 2108 list_for_each_entry(sroute, &sdev->route_list, list) { 2109 /* only set up routes belonging to static pipelines */ 2110 if (!verify && (sroute->src_widget->dynamic_pipeline_widget || 2111 sroute->sink_widget->dynamic_pipeline_widget)) 2112 continue; 2113 2114 /* 2115 * For virtual routes, both sink and source are not buffer. IPC3 only supports 2116 * connections between a buffer and a component. Ignore the rest. 2117 */ 2118 if (sroute->src_widget->id != snd_soc_dapm_buffer && 2119 sroute->sink_widget->id != snd_soc_dapm_buffer) 2120 continue; 2121 2122 ret = sof_route_setup(sdev, sroute->src_widget->widget, 2123 sroute->sink_widget->widget); 2124 if (ret < 0) { 2125 dev_err(sdev->dev, "%s: route set up failed\n", __func__); 2126 return ret; 2127 } 2128 } 2129 2130 /* complete pipeline */ 2131 list_for_each_entry(swidget, &sdev->widget_list, list) { 2132 switch (swidget->id) { 2133 case snd_soc_dapm_scheduler: 2134 /* only complete static pipelines */ 2135 if (!verify && swidget->dynamic_pipeline_widget) 2136 continue; 2137 2138 if (v->abi_version < SOF_ABI_VER(3, 19, 0)) { 2139 ret = sof_widget_setup(sdev, swidget); 2140 if (ret < 0) 2141 return ret; 2142 } 2143 2144 swidget->complete = sof_ipc3_complete_pipeline(sdev, swidget); 2145 if (swidget->complete < 0) 2146 return swidget->complete; 2147 break; 2148 default: 2149 break; 2150 } 2151 } 2152 2153 return 0; 2154 } 2155 2156 /* 2157 * Free the PCM, its associated widgets and set the prepared flag to false for all PCMs that 2158 * did not get suspended(ex: paused streams) so the widgets can be set up again during resume. 2159 */ 2160 static int sof_tear_down_left_over_pipelines(struct snd_sof_dev *sdev) 2161 { 2162 struct snd_sof_widget *swidget; 2163 struct snd_sof_pcm *spcm; 2164 int dir, ret; 2165 2166 /* 2167 * free all PCMs and their associated DAPM widgets if their connected DAPM widget 2168 * list is not NULL. This should only be true for paused streams at this point. 2169 * This is equivalent to the handling of FE DAI suspend trigger for running streams. 2170 */ 2171 list_for_each_entry(spcm, &sdev->pcm_list, list) { 2172 for_each_pcm_streams(dir) { 2173 struct snd_pcm_substream *substream = spcm->stream[dir].substream; 2174 2175 if (!substream || !substream->runtime) 2176 continue; 2177 2178 if (spcm->stream[dir].list) { 2179 ret = sof_pcm_stream_free(sdev, substream, spcm, dir, true); 2180 if (ret < 0) 2181 return ret; 2182 } 2183 } 2184 } 2185 2186 /* 2187 * free any left over DAI widgets. This is equivalent to the handling of suspend trigger 2188 * for the BE DAI for running streams. 2189 */ 2190 list_for_each_entry(swidget, &sdev->widget_list, list) 2191 if (WIDGET_IS_DAI(swidget->id) && swidget->use_count == 1) { 2192 ret = sof_widget_free(sdev, swidget); 2193 if (ret < 0) 2194 return ret; 2195 } 2196 2197 return 0; 2198 } 2199 2200 /* 2201 * For older firmware, this function doesn't free widgets for static pipelines during suspend. 2202 * It only resets use_count for all widgets. 2203 */ 2204 static int sof_ipc3_tear_down_all_pipelines(struct snd_sof_dev *sdev, bool verify) 2205 { 2206 struct sof_ipc_fw_version *v = &sdev->fw_ready.version; 2207 struct snd_sof_widget *swidget; 2208 struct snd_sof_route *sroute; 2209 int ret; 2210 2211 /* 2212 * This function is called during suspend and for one-time topology verification during 2213 * first boot. In both cases, there is no need to protect swidget->use_count and 2214 * sroute->setup because during suspend all running streams are suspended and during 2215 * topology loading the sound card unavailable to open PCMs. 2216 */ 2217 list_for_each_entry(swidget, &sdev->widget_list, list) { 2218 if (swidget->dynamic_pipeline_widget) 2219 continue; 2220 2221 /* Do not free widgets for static pipelines with FW ABI older than 3.19 */ 2222 if (!verify && !swidget->dynamic_pipeline_widget && 2223 v->abi_version < SOF_ABI_VER(3, 19, 0)) { 2224 swidget->use_count = 0; 2225 swidget->complete = 0; 2226 continue; 2227 } 2228 2229 ret = sof_widget_free(sdev, swidget); 2230 if (ret < 0) 2231 return ret; 2232 } 2233 2234 /* 2235 * Tear down all pipelines associated with PCMs that did not get suspended 2236 * and unset the prepare flag so that they can be set up again during resume. 2237 * Skip this step for older firmware. 2238 */ 2239 if (!verify && v->abi_version >= SOF_ABI_VER(3, 19, 0)) { 2240 ret = sof_tear_down_left_over_pipelines(sdev); 2241 if (ret < 0) { 2242 dev_err(sdev->dev, "failed to tear down paused pipelines\n"); 2243 return ret; 2244 } 2245 } 2246 2247 list_for_each_entry(sroute, &sdev->route_list, list) 2248 sroute->setup = false; 2249 2250 /* 2251 * before suspending, make sure the refcounts are all zeroed out. There's no way 2252 * to recover at this point but this will help root cause bad sequences leading to 2253 * more issues on resume 2254 */ 2255 list_for_each_entry(swidget, &sdev->widget_list, list) { 2256 if (swidget->use_count != 0) { 2257 dev_err(sdev->dev, "%s: widget %s is still in use: count %d\n", 2258 __func__, swidget->widget->name, swidget->use_count); 2259 } 2260 } 2261 2262 return 0; 2263 } 2264 2265 static int sof_ipc3_dai_get_clk(struct snd_sof_dev *sdev, struct snd_sof_dai *dai, int clk_type) 2266 { 2267 struct sof_dai_private_data *private = dai->private; 2268 2269 if (!private || !private->dai_config) 2270 return 0; 2271 2272 switch (private->dai_config->type) { 2273 case SOF_DAI_INTEL_SSP: 2274 switch (clk_type) { 2275 case SOF_DAI_CLK_INTEL_SSP_MCLK: 2276 return private->dai_config->ssp.mclk_rate; 2277 case SOF_DAI_CLK_INTEL_SSP_BCLK: 2278 return private->dai_config->ssp.bclk_rate; 2279 default: 2280 break; 2281 } 2282 dev_err(sdev->dev, "fail to get SSP clk %d rate\n", clk_type); 2283 break; 2284 default: 2285 /* not yet implemented for platforms other than the above */ 2286 dev_err(sdev->dev, "DAI type %d not supported yet!\n", private->dai_config->type); 2287 break; 2288 } 2289 2290 return -EINVAL; 2291 } 2292 2293 /* token list for each topology object */ 2294 static enum sof_tokens host_token_list[] = { 2295 SOF_CORE_TOKENS, 2296 SOF_COMP_EXT_TOKENS, 2297 SOF_PCM_TOKENS, 2298 SOF_COMP_TOKENS, 2299 }; 2300 2301 static enum sof_tokens comp_generic_token_list[] = { 2302 SOF_CORE_TOKENS, 2303 SOF_COMP_EXT_TOKENS, 2304 SOF_COMP_TOKENS, 2305 }; 2306 2307 static enum sof_tokens buffer_token_list[] = { 2308 SOF_BUFFER_TOKENS, 2309 }; 2310 2311 static enum sof_tokens pipeline_token_list[] = { 2312 SOF_CORE_TOKENS, 2313 SOF_COMP_EXT_TOKENS, 2314 SOF_PIPELINE_TOKENS, 2315 SOF_SCHED_TOKENS, 2316 }; 2317 2318 static enum sof_tokens asrc_token_list[] = { 2319 SOF_CORE_TOKENS, 2320 SOF_COMP_EXT_TOKENS, 2321 SOF_ASRC_TOKENS, 2322 SOF_COMP_TOKENS, 2323 }; 2324 2325 static enum sof_tokens src_token_list[] = { 2326 SOF_CORE_TOKENS, 2327 SOF_COMP_EXT_TOKENS, 2328 SOF_SRC_TOKENS, 2329 SOF_COMP_TOKENS 2330 }; 2331 2332 static enum sof_tokens pga_token_list[] = { 2333 SOF_CORE_TOKENS, 2334 SOF_COMP_EXT_TOKENS, 2335 SOF_VOLUME_TOKENS, 2336 SOF_COMP_TOKENS, 2337 }; 2338 2339 static enum sof_tokens dai_token_list[] = { 2340 SOF_CORE_TOKENS, 2341 SOF_COMP_EXT_TOKENS, 2342 SOF_DAI_TOKENS, 2343 SOF_COMP_TOKENS, 2344 }; 2345 2346 static enum sof_tokens process_token_list[] = { 2347 SOF_CORE_TOKENS, 2348 SOF_COMP_EXT_TOKENS, 2349 SOF_PROCESS_TOKENS, 2350 SOF_COMP_TOKENS, 2351 }; 2352 2353 static const struct sof_ipc_tplg_widget_ops tplg_ipc3_widget_ops[SND_SOC_DAPM_TYPE_COUNT] = { 2354 [snd_soc_dapm_aif_in] = {sof_ipc3_widget_setup_comp_host, sof_ipc3_widget_free_comp, 2355 host_token_list, ARRAY_SIZE(host_token_list), NULL}, 2356 [snd_soc_dapm_aif_out] = {sof_ipc3_widget_setup_comp_host, sof_ipc3_widget_free_comp, 2357 host_token_list, ARRAY_SIZE(host_token_list), NULL}, 2358 2359 [snd_soc_dapm_dai_in] = {sof_ipc3_widget_setup_comp_dai, sof_ipc3_widget_free_comp_dai, 2360 dai_token_list, ARRAY_SIZE(dai_token_list), NULL}, 2361 [snd_soc_dapm_dai_out] = {sof_ipc3_widget_setup_comp_dai, sof_ipc3_widget_free_comp_dai, 2362 dai_token_list, ARRAY_SIZE(dai_token_list), NULL}, 2363 [snd_soc_dapm_buffer] = {sof_ipc3_widget_setup_comp_buffer, sof_ipc3_widget_free_comp, 2364 buffer_token_list, ARRAY_SIZE(buffer_token_list), NULL}, 2365 [snd_soc_dapm_mixer] = {sof_ipc3_widget_setup_comp_mixer, sof_ipc3_widget_free_comp, 2366 comp_generic_token_list, ARRAY_SIZE(comp_generic_token_list), 2367 NULL}, 2368 [snd_soc_dapm_src] = {sof_ipc3_widget_setup_comp_src, sof_ipc3_widget_free_comp, 2369 src_token_list, ARRAY_SIZE(src_token_list), NULL}, 2370 [snd_soc_dapm_asrc] = {sof_ipc3_widget_setup_comp_asrc, sof_ipc3_widget_free_comp, 2371 asrc_token_list, ARRAY_SIZE(asrc_token_list), NULL}, 2372 [snd_soc_dapm_siggen] = {sof_ipc3_widget_setup_comp_tone, sof_ipc3_widget_free_comp, 2373 comp_generic_token_list, ARRAY_SIZE(comp_generic_token_list), 2374 NULL}, 2375 [snd_soc_dapm_scheduler] = {sof_ipc3_widget_setup_comp_pipeline, sof_ipc3_widget_free_comp, 2376 pipeline_token_list, ARRAY_SIZE(pipeline_token_list), NULL}, 2377 [snd_soc_dapm_pga] = {sof_ipc3_widget_setup_comp_pga, sof_ipc3_widget_free_comp, 2378 pga_token_list, ARRAY_SIZE(pga_token_list), NULL}, 2379 [snd_soc_dapm_mux] = {sof_ipc3_widget_setup_comp_mux, sof_ipc3_widget_free_comp, 2380 comp_generic_token_list, ARRAY_SIZE(comp_generic_token_list), NULL}, 2381 [snd_soc_dapm_demux] = {sof_ipc3_widget_setup_comp_mux, sof_ipc3_widget_free_comp, 2382 comp_generic_token_list, ARRAY_SIZE(comp_generic_token_list), 2383 NULL}, 2384 [snd_soc_dapm_effect] = {sof_widget_update_ipc_comp_process, sof_ipc3_widget_free_comp, 2385 process_token_list, ARRAY_SIZE(process_token_list), 2386 sof_ipc3_widget_bind_event}, 2387 }; 2388 2389 const struct sof_ipc_tplg_ops ipc3_tplg_ops = { 2390 .widget = tplg_ipc3_widget_ops, 2391 .control = &tplg_ipc3_control_ops, 2392 .route_setup = sof_ipc3_route_setup, 2393 .control_setup = sof_ipc3_control_setup, 2394 .control_free = sof_ipc3_control_free, 2395 .pipeline_complete = sof_ipc3_complete_pipeline, 2396 .token_list = ipc3_token_list, 2397 .widget_free = sof_ipc3_widget_free, 2398 .widget_setup = sof_ipc3_widget_setup, 2399 .dai_config = sof_ipc3_dai_config, 2400 .dai_get_clk = sof_ipc3_dai_get_clk, 2401 .set_up_all_pipelines = sof_ipc3_set_up_all_pipelines, 2402 .tear_down_all_pipelines = sof_ipc3_tear_down_all_pipelines, 2403 }; 2404